| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  | import { | 
					
						
							|  |  |  |   useCallback, | 
					
						
							|  |  |  |   useEffect, | 
					
						
							|  |  |  |   useMemo, | 
					
						
							|  |  |  |   useRef, | 
					
						
							|  |  |  |   useState, | 
					
						
							|  |  |  | } from 'react' | 
					
						
							|  |  |  | import { useTranslation } from 'react-i18next' | 
					
						
							|  |  |  | import useSWR from 'swr' | 
					
						
							|  |  |  | import { useLocalStorageState } from 'ahooks' | 
					
						
							|  |  |  | import produce from 'immer' | 
					
						
							|  |  |  | import type { | 
					
						
							|  |  |  |   ChatConfig, | 
					
						
							| 
									
										
										
										
											2025-02-08 11:59:02 +08:00
										 |  |  |   ChatItem, | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |   Feedback, | 
					
						
							|  |  |  | } from '../types' | 
					
						
							|  |  |  | import { CONVERSATION_ID_INFO } from '../constants' | 
					
						
							| 
									
										
										
										
											2025-04-16 21:08:13 +08:00
										 |  |  | import { buildChatItemTree, getProcessedInputsFromUrlParams, getProcessedSystemVariablesFromUrlParams } from '../utils' | 
					
						
							| 
									
										
										
										
											2025-02-08 11:59:02 +08:00
										 |  |  | import { getProcessedFilesFromResponse } from '../../file-uploader/utils' | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  | import { | 
					
						
							|  |  |  |   fetchAppInfo, | 
					
						
							|  |  |  |   fetchAppMeta, | 
					
						
							|  |  |  |   fetchAppParams, | 
					
						
							|  |  |  |   fetchChatList, | 
					
						
							|  |  |  |   fetchConversations, | 
					
						
							|  |  |  |   generationConversationName, | 
					
						
							|  |  |  |   updateFeedback, | 
					
						
							|  |  |  | } from '@/service/share' | 
					
						
							|  |  |  | import type { | 
					
						
							|  |  |  |   // AppData,
 | 
					
						
							|  |  |  |   ConversationItem, | 
					
						
							|  |  |  | } from '@/models/share' | 
					
						
							|  |  |  | import { useToastContext } from '@/app/components/base/toast' | 
					
						
							|  |  |  | import { changeLanguage } from '@/i18n/i18next-config' | 
					
						
							| 
									
										
										
										
											2024-10-21 10:32:37 +08:00
										 |  |  | import { InputVarType } from '@/app/components/workflow/types' | 
					
						
							|  |  |  | import { TransferMethod } from '@/types/app' | 
					
						
							| 
									
										
										
										
											2025-02-08 11:59:02 +08:00
										 |  |  | import { addFileInfos, sortAgentSorts } from '@/app/components/tools/utils' | 
					
						
							| 
									
										
										
										
											2025-04-06 17:56:08 +08:00
										 |  |  | import { noop } from 'lodash-es' | 
					
						
							| 
									
										
										
										
											2025-05-20 12:07:50 +08:00
										 |  |  | import { useGetAppAccessMode, useGetUserCanAccessApp } from '@/service/access-control' | 
					
						
							|  |  |  | import { useGlobalPublicStore } from '@/context/global-public-context' | 
					
						
							|  |  |  | import { AccessMode } from '@/models/access-control' | 
					
						
							| 
									
										
										
										
											2025-02-08 11:59:02 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | function getFormattedChatList(messages: any[]) { | 
					
						
							|  |  |  |   const newChatList: ChatItem[] = [] | 
					
						
							|  |  |  |   messages.forEach((item) => { | 
					
						
							|  |  |  |     const questionFiles = item.message_files?.filter((file: any) => file.belongs_to === 'user') || [] | 
					
						
							|  |  |  |     newChatList.push({ | 
					
						
							|  |  |  |       id: `question-${item.id}`, | 
					
						
							|  |  |  |       content: item.query, | 
					
						
							|  |  |  |       isAnswer: false, | 
					
						
							|  |  |  |       message_files: getProcessedFilesFromResponse(questionFiles.map((item: any) => ({ ...item, related_id: item.id }))), | 
					
						
							|  |  |  |       parentMessageId: item.parent_message_id || undefined, | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |     const answerFiles = item.message_files?.filter((file: any) => file.belongs_to === 'assistant') || [] | 
					
						
							|  |  |  |     newChatList.push({ | 
					
						
							|  |  |  |       id: item.id, | 
					
						
							|  |  |  |       content: item.answer, | 
					
						
							|  |  |  |       agent_thoughts: addFileInfos(item.agent_thoughts ? sortAgentSorts(item.agent_thoughts) : item.agent_thoughts, item.message_files), | 
					
						
							|  |  |  |       feedback: item.feedback, | 
					
						
							|  |  |  |       isAnswer: true, | 
					
						
							|  |  |  |       citation: item.retriever_resources, | 
					
						
							|  |  |  |       message_files: getProcessedFilesFromResponse(answerFiles.map((item: any) => ({ ...item, related_id: item.id }))), | 
					
						
							|  |  |  |       parentMessageId: `question-${item.id}`, | 
					
						
							|  |  |  |     }) | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  |   return newChatList | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | export const useEmbeddedChatbot = () => { | 
					
						
							|  |  |  |   const isInstalledApp = false | 
					
						
							| 
									
										
										
										
											2025-05-20 12:07:50 +08:00
										 |  |  |   const systemFeatures = useGlobalPublicStore(s => s.systemFeatures) | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |   const { data: appInfo, isLoading: appInfoLoading, error: appInfoError } = useSWR('appInfo', fetchAppInfo) | 
					
						
							| 
									
										
										
										
											2025-05-20 12:07:50 +08:00
										 |  |  |   const { isPending: isGettingAccessMode, data: appAccessMode } = useGetAppAccessMode({ | 
					
						
							|  |  |  |     appId: appInfo?.app_id, | 
					
						
							|  |  |  |     isInstalledApp, | 
					
						
							|  |  |  |     enabled: systemFeatures.webapp_auth.enabled, | 
					
						
							|  |  |  |   }) | 
					
						
							|  |  |  |   const { isPending: isCheckingPermission, data: userCanAccessResult } = useGetUserCanAccessApp({ | 
					
						
							|  |  |  |     appId: appInfo?.app_id, | 
					
						
							|  |  |  |     isInstalledApp, | 
					
						
							|  |  |  |     enabled: systemFeatures.webapp_auth.enabled, | 
					
						
							|  |  |  |   }) | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const appData = useMemo(() => { | 
					
						
							|  |  |  |     return appInfo | 
					
						
							|  |  |  |   }, [appInfo]) | 
					
						
							|  |  |  |   const appId = useMemo(() => appData?.app_id, [appData]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-16 21:08:13 +08:00
										 |  |  |   const [userId, setUserId] = useState<string>() | 
					
						
							| 
									
										
										
										
											2025-04-23 16:48:45 +08:00
										 |  |  |   const [conversationId, setConversationId] = useState<string>() | 
					
						
							| 
									
										
										
										
											2025-04-16 21:08:13 +08:00
										 |  |  |   useEffect(() => { | 
					
						
							| 
									
										
										
										
											2025-04-23 16:48:45 +08:00
										 |  |  |     getProcessedSystemVariablesFromUrlParams().then(({ user_id, conversation_id }) => { | 
					
						
							| 
									
										
										
										
											2025-04-16 21:08:13 +08:00
										 |  |  |       setUserId(user_id) | 
					
						
							| 
									
										
										
										
											2025-04-23 16:48:45 +08:00
										 |  |  |       setConversationId(conversation_id) | 
					
						
							| 
									
										
										
										
											2025-04-16 21:08:13 +08:00
										 |  |  |     }) | 
					
						
							|  |  |  |   }, []) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |   useEffect(() => { | 
					
						
							| 
									
										
										
										
											2025-04-21 23:03:01 -04:00
										 |  |  |     const setLanguageFromParams = async () => { | 
					
						
							|  |  |  |       // Check URL parameters for language override
 | 
					
						
							|  |  |  |       const urlParams = new URLSearchParams(window.location.search) | 
					
						
							|  |  |  |       const localeParam = urlParams.get('locale') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Check for encoded system variables
 | 
					
						
							|  |  |  |       const systemVariables = await getProcessedSystemVariablesFromUrlParams() | 
					
						
							|  |  |  |       const localeFromSysVar = systemVariables.locale | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (localeParam) { | 
					
						
							|  |  |  |         // If locale parameter exists in URL, use it instead of default
 | 
					
						
							|  |  |  |         changeLanguage(localeParam) | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else if (localeFromSysVar) { | 
					
						
							|  |  |  |         // If locale is set as a system variable, use that
 | 
					
						
							|  |  |  |         changeLanguage(localeFromSysVar) | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       else if (appInfo?.site.default_language) { | 
					
						
							|  |  |  |         // Otherwise use the default from app config
 | 
					
						
							|  |  |  |         changeLanguage(appInfo.site.default_language) | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     setLanguageFromParams() | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |   }, [appInfo]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-04-16 21:08:13 +08:00
										 |  |  |   const [conversationIdInfo, setConversationIdInfo] = useLocalStorageState<Record<string, Record<string, string>>>(CONVERSATION_ID_INFO, { | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |     defaultValue: {}, | 
					
						
							|  |  |  |   }) | 
					
						
							| 
									
										
										
										
											2025-04-23 22:57:42 +08:00
										 |  |  |   const allowResetChat = !conversationId | 
					
						
							| 
									
										
										
										
											2025-04-23 16:48:45 +08:00
										 |  |  |   const currentConversationId = useMemo(() => conversationIdInfo?.[appId || '']?.[userId || 'DEFAULT'] || conversationId || '', | 
					
						
							|  |  |  |     [appId, conversationIdInfo, userId, conversationId]) | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |   const handleConversationIdInfoChange = useCallback((changeConversationId: string) => { | 
					
						
							|  |  |  |     if (appId) { | 
					
						
							| 
									
										
										
										
											2025-04-16 21:08:13 +08:00
										 |  |  |       let prevValue = conversationIdInfo?.[appId || ''] | 
					
						
							|  |  |  |       if (typeof prevValue === 'string') | 
					
						
							|  |  |  |         prevValue = {} | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |       setConversationIdInfo({ | 
					
						
							|  |  |  |         ...conversationIdInfo, | 
					
						
							| 
									
										
										
										
											2025-04-16 21:08:13 +08:00
										 |  |  |         [appId || '']: { | 
					
						
							|  |  |  |           ...prevValue, | 
					
						
							|  |  |  |           [userId || 'DEFAULT']: changeConversationId, | 
					
						
							|  |  |  |         }, | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |       }) | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-04-16 21:08:13 +08:00
										 |  |  |   }, [appId, conversationIdInfo, setConversationIdInfo, userId]) | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const [newConversationId, setNewConversationId] = useState('') | 
					
						
							|  |  |  |   const chatShouldReloadKey = useMemo(() => { | 
					
						
							|  |  |  |     if (currentConversationId === newConversationId) | 
					
						
							|  |  |  |       return '' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return currentConversationId | 
					
						
							|  |  |  |   }, [currentConversationId, newConversationId]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const { data: appParams } = useSWR(['appParams', isInstalledApp, appId], () => fetchAppParams(isInstalledApp, appId)) | 
					
						
							|  |  |  |   const { data: appMeta } = useSWR(['appMeta', isInstalledApp, appId], () => fetchAppMeta(isInstalledApp, appId)) | 
					
						
							|  |  |  |   const { data: appPinnedConversationData } = useSWR(['appConversationData', isInstalledApp, appId, true], () => fetchConversations(isInstalledApp, appId, undefined, true, 100)) | 
					
						
							|  |  |  |   const { data: appConversationData, isLoading: appConversationDataLoading, mutate: mutateAppConversationData } = useSWR(['appConversationData', isInstalledApp, appId, false], () => fetchConversations(isInstalledApp, appId, undefined, false, 100)) | 
					
						
							|  |  |  |   const { data: appChatListData, isLoading: appChatListDataLoading } = useSWR(chatShouldReloadKey ? ['appChatList', chatShouldReloadKey, isInstalledApp, appId] : null, () => fetchChatList(chatShouldReloadKey, isInstalledApp, appId)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-13 14:23:41 +08:00
										 |  |  |   const [clearChatList, setClearChatList] = useState(false) | 
					
						
							|  |  |  |   const [isResponding, setIsResponding] = useState(false) | 
					
						
							| 
									
										
										
										
											2024-09-22 03:15:11 +08:00
										 |  |  |   const appPrevChatList = useMemo( | 
					
						
							|  |  |  |     () => (currentConversationId && appChatListData?.data.length) | 
					
						
							| 
									
										
										
										
											2025-02-08 11:59:02 +08:00
										 |  |  |       ? buildChatItemTree(getFormattedChatList(appChatListData.data)) | 
					
						
							| 
									
										
										
										
											2024-09-22 03:15:11 +08:00
										 |  |  |       : [], | 
					
						
							|  |  |  |     [appChatListData, currentConversationId], | 
					
						
							|  |  |  |   ) | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const [showNewConversationItemInList, setShowNewConversationItemInList] = useState(false) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const pinnedConversationList = useMemo(() => { | 
					
						
							|  |  |  |     return appPinnedConversationData?.data || [] | 
					
						
							|  |  |  |   }, [appPinnedConversationData]) | 
					
						
							|  |  |  |   const { t } = useTranslation() | 
					
						
							|  |  |  |   const newConversationInputsRef = useRef<Record<string, any>>({}) | 
					
						
							|  |  |  |   const [newConversationInputs, setNewConversationInputs] = useState<Record<string, any>>({}) | 
					
						
							| 
									
										
										
										
											2024-07-18 21:54:16 +08:00
										 |  |  |   const [initInputs, setInitInputs] = useState<Record<string, any>>({}) | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |   const handleNewConversationInputsChange = useCallback((newInputs: Record<string, any>) => { | 
					
						
							|  |  |  |     newConversationInputsRef.current = newInputs | 
					
						
							|  |  |  |     setNewConversationInputs(newInputs) | 
					
						
							|  |  |  |   }, []) | 
					
						
							|  |  |  |   const inputsForms = useMemo(() => { | 
					
						
							| 
									
										
										
										
											2024-10-21 10:32:37 +08:00
										 |  |  |     return (appParams?.user_input_form || []).filter((item: any) => !item.external_data_tool).map((item: any) => { | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |       if (item.paragraph) { | 
					
						
							| 
									
										
										
										
											2024-07-18 21:54:16 +08:00
										 |  |  |         let value = initInputs[item.paragraph.variable] | 
					
						
							|  |  |  |         if (value && item.paragraph.max_length && value.length > item.paragraph.max_length) | 
					
						
							|  |  |  |           value = value.slice(0, item.paragraph.max_length) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |         return { | 
					
						
							|  |  |  |           ...item.paragraph, | 
					
						
							| 
									
										
										
										
											2024-07-18 21:54:16 +08:00
										 |  |  |           default: value || item.default, | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |           type: 'paragraph', | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (item.number) { | 
					
						
							| 
									
										
										
										
											2024-07-18 21:54:16 +08:00
										 |  |  |         const convertedNumber = Number(initInputs[item.number.variable]) ?? undefined | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |         return { | 
					
						
							|  |  |  |           ...item.number, | 
					
						
							| 
									
										
										
										
											2024-07-18 21:54:16 +08:00
										 |  |  |           default: convertedNumber || item.default, | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |           type: 'number', | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (item.select) { | 
					
						
							| 
									
										
										
										
											2024-07-18 21:54:16 +08:00
										 |  |  |         const isInputInOptions = item.select.options.includes(initInputs[item.select.variable]) | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |         return { | 
					
						
							|  |  |  |           ...item.select, | 
					
						
							| 
									
										
										
										
											2024-07-18 21:54:16 +08:00
										 |  |  |           default: (isInputInOptions ? initInputs[item.select.variable] : undefined) || item.default, | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |           type: 'select', | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-21 10:32:37 +08:00
										 |  |  |       if (item['file-list']) { | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |           ...item['file-list'], | 
					
						
							|  |  |  |           type: 'file-list', | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (item.file) { | 
					
						
							|  |  |  |         return { | 
					
						
							|  |  |  |           ...item.file, | 
					
						
							|  |  |  |           type: 'file', | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-18 21:54:16 +08:00
										 |  |  |       let value = initInputs[item['text-input'].variable] | 
					
						
							|  |  |  |       if (value && item['text-input'].max_length && value.length > item['text-input'].max_length) | 
					
						
							|  |  |  |         value = value.slice(0, item['text-input'].max_length) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |       return { | 
					
						
							|  |  |  |         ...item['text-input'], | 
					
						
							| 
									
										
										
										
											2024-07-18 21:54:16 +08:00
										 |  |  |         default: value || item.default, | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |         type: 'text-input', | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }) | 
					
						
							| 
									
										
										
										
											2024-09-22 03:15:11 +08:00
										 |  |  |   }, [initInputs, appParams]) | 
					
						
							| 
									
										
										
										
											2024-07-18 21:54:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-05-21 13:52:21 +08:00
										 |  |  |   const allInputsHidden = useMemo(() => { | 
					
						
							|  |  |  |     return inputsForms.length > 0 && inputsForms.every(item => item.hide === true) | 
					
						
							|  |  |  |   }, [inputsForms]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-18 21:54:16 +08:00
										 |  |  |   useEffect(() => { | 
					
						
							|  |  |  |     // init inputs from url params
 | 
					
						
							| 
									
										
										
										
											2025-03-20 00:17:58 +08:00
										 |  |  |     (async () => { | 
					
						
							|  |  |  |       const inputs = await getProcessedInputsFromUrlParams() | 
					
						
							|  |  |  |       setInitInputs(inputs) | 
					
						
							|  |  |  |     })() | 
					
						
							| 
									
										
										
										
											2024-07-18 21:54:16 +08:00
										 |  |  |   }, []) | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |   useEffect(() => { | 
					
						
							|  |  |  |     const conversationInputs: Record<string, any> = {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     inputsForms.forEach((item: any) => { | 
					
						
							| 
									
										
										
										
											2024-11-11 14:57:28 +08:00
										 |  |  |       conversationInputs[item.variable] = item.default || null | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |     }) | 
					
						
							|  |  |  |     handleNewConversationInputsChange(conversationInputs) | 
					
						
							|  |  |  |   }, [handleNewConversationInputsChange, inputsForms]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const { data: newConversation } = useSWR(newConversationId ? [isInstalledApp, appId, newConversationId] : null, () => generationConversationName(isInstalledApp, appId, newConversationId), { revalidateOnFocus: false }) | 
					
						
							|  |  |  |   const [originConversationList, setOriginConversationList] = useState<ConversationItem[]>([]) | 
					
						
							|  |  |  |   useEffect(() => { | 
					
						
							|  |  |  |     if (appConversationData?.data && !appConversationDataLoading) | 
					
						
							|  |  |  |       setOriginConversationList(appConversationData?.data) | 
					
						
							|  |  |  |   }, [appConversationData, appConversationDataLoading]) | 
					
						
							|  |  |  |   const conversationList = useMemo(() => { | 
					
						
							|  |  |  |     const data = originConversationList.slice() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (showNewConversationItemInList && data[0]?.id !== '') { | 
					
						
							|  |  |  |       data.unshift({ | 
					
						
							|  |  |  |         id: '', | 
					
						
							|  |  |  |         name: t('share.chat.newChatDefaultName'), | 
					
						
							|  |  |  |         inputs: {}, | 
					
						
							|  |  |  |         introduction: '', | 
					
						
							|  |  |  |       }) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return data | 
					
						
							|  |  |  |   }, [originConversationList, showNewConversationItemInList, t]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   useEffect(() => { | 
					
						
							|  |  |  |     if (newConversation) { | 
					
						
							|  |  |  |       setOriginConversationList(produce((draft) => { | 
					
						
							|  |  |  |         const index = draft.findIndex(item => item.id === newConversation.id) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (index > -1) | 
					
						
							|  |  |  |           draft[index] = newConversation | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |           draft.unshift(newConversation) | 
					
						
							|  |  |  |       })) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   }, [newConversation]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const currentConversationItem = useMemo(() => { | 
					
						
							|  |  |  |     let conversationItem = conversationList.find(item => item.id === currentConversationId) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!conversationItem && pinnedConversationList.length) | 
					
						
							|  |  |  |       conversationItem = pinnedConversationList.find(item => item.id === currentConversationId) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return conversationItem | 
					
						
							|  |  |  |   }, [conversationList, currentConversationId, pinnedConversationList]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2025-03-27 11:58:16 +08:00
										 |  |  |   const currentConversationLatestInputs = useMemo(() => { | 
					
						
							|  |  |  |     if (!currentConversationId || !appChatListData?.data.length) | 
					
						
							| 
									
										
										
										
											2025-04-10 13:58:35 +08:00
										 |  |  |       return newConversationInputsRef.current || {} | 
					
						
							| 
									
										
										
										
											2025-03-27 11:58:16 +08:00
										 |  |  |     return appChatListData.data.slice().pop().inputs || {} | 
					
						
							|  |  |  |   }, [appChatListData, currentConversationId]) | 
					
						
							|  |  |  |   const [currentConversationInputs, setCurrentConversationInputs] = useState<Record<string, any>>(currentConversationLatestInputs || {}) | 
					
						
							|  |  |  |   useEffect(() => { | 
					
						
							|  |  |  |     if (currentConversationItem) | 
					
						
							|  |  |  |       setCurrentConversationInputs(currentConversationLatestInputs || {}) | 
					
						
							|  |  |  |   }, [currentConversationItem, currentConversationLatestInputs]) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |   const { notify } = useToastContext() | 
					
						
							|  |  |  |   const checkInputsRequired = useCallback((silent?: boolean) => { | 
					
						
							| 
									
										
										
										
											2025-05-21 13:52:21 +08:00
										 |  |  |     if (allInputsHidden) | 
					
						
							|  |  |  |       return true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-10-21 10:32:37 +08:00
										 |  |  |     let hasEmptyInput = '' | 
					
						
							|  |  |  |     let fileIsUploading = false | 
					
						
							|  |  |  |     const requiredVars = inputsForms.filter(({ required }) => required) | 
					
						
							|  |  |  |     if (requiredVars.length) { | 
					
						
							|  |  |  |       requiredVars.forEach(({ variable, label, type }) => { | 
					
						
							|  |  |  |         if (hasEmptyInput) | 
					
						
							|  |  |  |           return | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (fileIsUploading) | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |           return | 
					
						
							| 
									
										
										
										
											2024-10-21 10:32:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (!newConversationInputsRef.current[variable] && !silent) | 
					
						
							|  |  |  |           hasEmptyInput = label as string | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if ((type === InputVarType.singleFile || type === InputVarType.multiFiles) && newConversationInputsRef.current[variable] && !silent) { | 
					
						
							|  |  |  |           const files = newConversationInputsRef.current[variable] | 
					
						
							|  |  |  |           if (Array.isArray(files)) | 
					
						
							|  |  |  |             fileIsUploading = files.find(item => item.transferMethod === TransferMethod.local_file && !item.uploadedId) | 
					
						
							|  |  |  |           else | 
					
						
							|  |  |  |             fileIsUploading = files.transferMethod === TransferMethod.local_file && !files.uploadedId | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2024-10-21 10:32:37 +08:00
										 |  |  |       }) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (hasEmptyInput) { | 
					
						
							|  |  |  |       notify({ type: 'error', message: t('appDebug.errorMessage.valueOfVarRequired', { key: hasEmptyInput }) }) | 
					
						
							|  |  |  |       return false | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (fileIsUploading) { | 
					
						
							|  |  |  |       notify({ type: 'info', message: t('appDebug.errorMessage.waitForFileUpload') }) | 
					
						
							|  |  |  |       return | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return true | 
					
						
							| 
									
										
										
										
											2025-05-21 13:52:21 +08:00
										 |  |  |   }, [inputsForms, notify, t, allInputsHidden]) | 
					
						
							| 
									
										
										
										
											2025-03-03 14:44:51 +08:00
										 |  |  |   const handleStartChat = useCallback((callback?: any) => { | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |     if (checkInputsRequired()) { | 
					
						
							|  |  |  |       setShowNewConversationItemInList(true) | 
					
						
							| 
									
										
										
										
											2025-03-03 14:44:51 +08:00
										 |  |  |       callback?.() | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2025-03-03 14:44:51 +08:00
										 |  |  |   }, [setShowNewConversationItemInList, checkInputsRequired]) | 
					
						
							| 
									
										
										
										
											2025-04-06 17:56:08 +08:00
										 |  |  |   const currentChatInstanceRef = useRef<{ handleStop: () => void }>({ handleStop: noop }) | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |   const handleChangeConversation = useCallback((conversationId: string) => { | 
					
						
							|  |  |  |     currentChatInstanceRef.current.handleStop() | 
					
						
							|  |  |  |     setNewConversationId('') | 
					
						
							|  |  |  |     handleConversationIdInfoChange(conversationId) | 
					
						
							| 
									
										
										
										
											2025-03-13 14:23:41 +08:00
										 |  |  |     if (conversationId) | 
					
						
							|  |  |  |       setClearChatList(false) | 
					
						
							|  |  |  |   }, [handleConversationIdInfoChange, setClearChatList]) | 
					
						
							| 
									
										
										
										
											2025-03-20 00:17:58 +08:00
										 |  |  |   const handleNewConversation = useCallback(async () => { | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |     currentChatInstanceRef.current.handleStop() | 
					
						
							| 
									
										
										
										
											2025-03-13 14:23:41 +08:00
										 |  |  |     setShowNewConversationItemInList(true) | 
					
						
							|  |  |  |     handleChangeConversation('') | 
					
						
							| 
									
										
										
										
											2025-03-20 00:17:58 +08:00
										 |  |  |     handleNewConversationInputsChange(await getProcessedInputsFromUrlParams()) | 
					
						
							| 
									
										
										
										
											2025-03-13 14:23:41 +08:00
										 |  |  |     setClearChatList(true) | 
					
						
							|  |  |  |   }, [handleChangeConversation, setShowNewConversationItemInList, handleNewConversationInputsChange, setClearChatList]) | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   const handleNewConversationCompleted = useCallback((newConversationId: string) => { | 
					
						
							|  |  |  |     setNewConversationId(newConversationId) | 
					
						
							|  |  |  |     handleConversationIdInfoChange(newConversationId) | 
					
						
							|  |  |  |     setShowNewConversationItemInList(false) | 
					
						
							|  |  |  |     mutateAppConversationData() | 
					
						
							|  |  |  |   }, [mutateAppConversationData, handleConversationIdInfoChange]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   const handleFeedback = useCallback(async (messageId: string, feedback: Feedback) => { | 
					
						
							|  |  |  |     await updateFeedback({ url: `/messages/${messageId}/feedbacks`, body: { rating: feedback.rating } }, isInstalledApp, appId) | 
					
						
							|  |  |  |     notify({ type: 'success', message: t('common.api.success') }) | 
					
						
							|  |  |  |   }, [isInstalledApp, appId, t, notify]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return { | 
					
						
							|  |  |  |     appInfoError, | 
					
						
							| 
									
										
										
										
											2025-05-20 12:07:50 +08:00
										 |  |  |     appInfoLoading: appInfoLoading || (systemFeatures.webapp_auth.enabled && (isGettingAccessMode || isCheckingPermission)), | 
					
						
							|  |  |  |     accessMode: systemFeatures.webapp_auth.enabled ? appAccessMode?.accessMode : AccessMode.PUBLIC, | 
					
						
							|  |  |  |     userCanAccess: systemFeatures.webapp_auth.enabled ? userCanAccessResult?.result : true, | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |     isInstalledApp, | 
					
						
							| 
									
										
										
										
											2025-04-23 22:57:42 +08:00
										 |  |  |     allowResetChat, | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |     appId, | 
					
						
							|  |  |  |     currentConversationId, | 
					
						
							|  |  |  |     currentConversationItem, | 
					
						
							|  |  |  |     handleConversationIdInfoChange, | 
					
						
							|  |  |  |     appData, | 
					
						
							|  |  |  |     appParams: appParams || {} as ChatConfig, | 
					
						
							|  |  |  |     appMeta, | 
					
						
							|  |  |  |     appPinnedConversationData, | 
					
						
							|  |  |  |     appConversationData, | 
					
						
							|  |  |  |     appConversationDataLoading, | 
					
						
							|  |  |  |     appChatListData, | 
					
						
							|  |  |  |     appChatListDataLoading, | 
					
						
							|  |  |  |     appPrevChatList, | 
					
						
							|  |  |  |     pinnedConversationList, | 
					
						
							|  |  |  |     conversationList, | 
					
						
							|  |  |  |     setShowNewConversationItemInList, | 
					
						
							|  |  |  |     newConversationInputs, | 
					
						
							| 
									
										
										
										
											2024-10-21 10:32:37 +08:00
										 |  |  |     newConversationInputsRef, | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |     handleNewConversationInputsChange, | 
					
						
							|  |  |  |     inputsForms, | 
					
						
							|  |  |  |     handleNewConversation, | 
					
						
							|  |  |  |     handleStartChat, | 
					
						
							|  |  |  |     handleChangeConversation, | 
					
						
							|  |  |  |     handleNewConversationCompleted, | 
					
						
							|  |  |  |     newConversationId, | 
					
						
							|  |  |  |     chatShouldReloadKey, | 
					
						
							|  |  |  |     handleFeedback, | 
					
						
							|  |  |  |     currentChatInstanceRef, | 
					
						
							| 
									
										
										
										
											2025-03-13 14:23:41 +08:00
										 |  |  |     clearChatList, | 
					
						
							|  |  |  |     setClearChatList, | 
					
						
							|  |  |  |     isResponding, | 
					
						
							|  |  |  |     setIsResponding, | 
					
						
							| 
									
										
										
										
											2025-03-27 11:58:16 +08:00
										 |  |  |     currentConversationInputs, | 
					
						
							|  |  |  |     setCurrentConversationInputs, | 
					
						
							| 
									
										
										
										
											2025-05-21 13:52:21 +08:00
										 |  |  |     allInputsHidden, | 
					
						
							| 
									
										
										
										
											2024-06-14 08:42:41 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | } |