Fix/embedding chat (#899)

Co-authored-by: Joel <iamjoel007@gmail.com>
This commit is contained in:
zxhlyh 2023-08-18 10:39:05 +08:00 committed by GitHub
parent 9adbeadeec
commit fb62017e50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 36 additions and 95 deletions

View File

@ -12,13 +12,12 @@ import AppUnavailable from '../../base/app-unavailable'
import useConversation from './hooks/use-conversation'
import s from './style.module.css'
import { ToastContext } from '@/app/components/base/toast'
import Sidebar from '@/app/components/share/chatbot/sidebar'
import ConfigScene from '@/app/components/share/chatbot/config-scence'
import Header from '@/app/components/share/header'
import { /* delConversation, */ fetchAppInfo, fetchAppParams, fetchChatList, fetchConversations, fetchSuggestedQuestions, pinConversation, sendChatMessage, stopChatMessageResponding, unpinConversation, updateFeedback } from '@/service/share'
import { fetchAppInfo, fetchAppParams, fetchChatList, fetchConversations, fetchSuggestedQuestions, sendChatMessage, stopChatMessageResponding, updateFeedback } from '@/service/share'
import type { ConversationItem, SiteInfo } from '@/models/share'
import type { PromptConfig, SuggestedQuestionsAfterAnswerConfig } from '@/models/debug'
import type { Feedbacktype, IChatItem } from '@/app/components/app/chat'
import type { Feedbacktype, IChatItem } from '@/app/components/app/chat/type'
import Chat from '@/app/components/app/chat'
import { changeLanguage } from '@/i18n/i18next-config'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
@ -26,7 +25,7 @@ import Loading from '@/app/components/base/loading'
import { replaceStringWithValues } from '@/app/components/app/configuration/prompt-value-panel'
import { userInputsFormToPromptVariables } from '@/utils/model-config'
import type { InstalledApp } from '@/models/explore'
// import Confirm from '@/app/components/base/confirm'
import { AlertTriangle } from '@/app/components/base/icons/src/vender/solid/alertsAndFeedback'
export type IMainProps = {
isInstalledApp?: boolean
@ -52,8 +51,6 @@ const Main: FC<IMainProps> = ({
const [promptConfig, setPromptConfig] = useState<PromptConfig | null>(null)
const [inited, setInited] = useState<boolean>(false)
const [plan, setPlan] = useState<string>('basic') // basic/plus/pro
// in mobile, show sidebar by click button
const [isShowSidebar, { setTrue: showSidebar, setFalse: hideSidebar }] = useBoolean(false)
// Can Use metadata(https://beta.nextjs.org/docs/api-reference/metadata) to set title. But it only works in server side client.
useEffect(() => {
if (siteInfo?.title) {
@ -124,37 +121,6 @@ const Main: FC<IMainProps> = ({
setControlUpdateConversationList(Date.now())
}
const handlePin = async (id: string) => {
await pinConversation(isInstalledApp, installedAppInfo?.id, id)
notify({ type: 'success', message: t('common.api.success') })
noticeUpdateList()
}
const handleUnpin = async (id: string) => {
await unpinConversation(isInstalledApp, installedAppInfo?.id, id)
notify({ type: 'success', message: t('common.api.success') })
noticeUpdateList()
}
const [isShowConfirm, { setTrue: showConfirm, setFalse: hideConfirm }] = useBoolean(false)
const [toDeleteConversationId, setToDeleteConversationId] = useState('')
const handleDelete = (id: string) => {
setToDeleteConversationId(id)
hideSidebar() // mobile
showConfirm()
}
// const didDelete = async () => {
// await delConversation(isInstalledApp, installedAppInfo?.id, toDeleteConversationId)
// notify({ type: 'success', message: t('common.api.success') })
// hideConfirm()
// if (currConversationId === toDeleteConversationId)
// handleConversationIdChange('-1')
// noticeUpdateList()
// }
const [suggestedQuestionsAfterAnswerConfig, setSuggestedQuestionsAfterAnswerConfig] = useState<SuggestedQuestionsAfterAnswerConfig | null>(null)
const [speechToTextConfig, setSpeechToTextConfig] = useState<SuggestedQuestionsAfterAnswerConfig | null>(null)
@ -235,20 +201,6 @@ const Main: FC<IMainProps> = ({
}
useEffect(handleConversationSwitch, [currConversationId, inited])
const handleConversationIdChange = (id: string) => {
if (id === '-1') {
createNewChat()
setConversationIdChangeBecauseOfNew(true)
}
else {
setConversationIdChangeBecauseOfNew(false)
}
// trigger handleConversationSwitch
setCurrConversationId(id, appId)
setIsShowSuggestion(false)
hideSidebar()
}
/*
* chat info. chat is under conversation.
*/
@ -416,6 +368,7 @@ const Main: FC<IMainProps> = ({
const [suggestQuestions, setSuggestQuestions] = useState<string[]>([])
const [messageTaskId, setMessageTaskId] = useState('')
const [hasStopResponded, setHasStopResponded, getHasStopResponded] = useGetState(false)
const [shouldReload, setShouldReload] = useState(false)
const handleSend = async (message: string) => {
if (isResponsing) {
@ -500,7 +453,9 @@ const Main: FC<IMainProps> = ({
setIsShowSuggestion(true)
}
},
onError() {
onError(errorMessage, errorCode) {
if (['provider_not_initialize', 'completion_request_error'].includes(errorCode as string))
setShouldReload(true)
setResponsingFalse()
// role back placeholder answer
setChatList(produce(getChatList(), (draft) => {
@ -525,31 +480,11 @@ const Main: FC<IMainProps> = ({
notify({ type: 'success', message: t('common.api.success') })
}
const renderSidebar = () => {
if (!appId || !siteInfo || !promptConfig)
return null
return (
<Sidebar
list={conversationList}
isClearConversationList={isClearConversationList}
pinnedList={pinnedConversationList}
isClearPinnedConversationList={isClearPinnedConversationList}
onMoreLoaded={onMoreLoaded}
onPinnedMoreLoaded={onPinnedMoreLoaded}
isNoMore={!hasMore}
isPinnedNoMore={!hasPinnedMore}
onCurrentIdChange={handleConversationIdChange}
currentId={currConversationId}
copyRight={siteInfo.copyright || siteInfo.title}
isInstalledApp={isInstalledApp}
installedAppId={installedAppInfo?.id}
siteInfo={siteInfo}
onPin={handlePin}
onUnpin={handleUnpin}
controlUpdateList={controlUpdateConversationList}
onDelete={handleDelete}
/>
)
const handleReload = () => {
setCurrConversationId('-1', appId, false)
setChatNotStarted()
setShouldReload(false)
createNewChat()
}
const difyIcon = (
@ -571,24 +506,9 @@ const Main: FC<IMainProps> = ({
icon_background={siteInfo.icon_background}
isEmbedScene={true}
isMobile={isMobile}
// onShowSideBar={showSidebar}
// onCreateNewChat={() => handleConversationIdChange('-1')}
/>
<div className={'flex bg-white overflow-hidden'}>
{/* sidebar */}
{/* {!isMobile && renderSidebar()} */}
{/* {isMobile && isShowSidebar && (
<div className='fixed inset-0 z-50'
style={{ backgroundColor: 'rgba(35, 56, 118, 0.2)' }}
onClick={hideSidebar}
>
<div className='inline-block' onClick={e => e.stopPropagation()}>
{renderSidebar()}
</div>
</div>
)} */}
{/* main */}
<div className={cn(
isInstalledApp ? s.installedApp : 'h-[calc(100vh_-_3rem)]',
'flex-grow flex flex-col overflow-y-auto',
@ -606,7 +526,22 @@ const Main: FC<IMainProps> = ({
onInputsChange={setCurrInputs}
plan={plan}
></ConfigScene>
{
shouldReload && (
<div className='flex items-center justify-between mb-5 px-4 py-2 bg-[#FEF0C7]'>
<div className='flex items-center text-xs font-medium text-[#DC6803]'>
<AlertTriangle className='mr-2 w-4 h-4' />
{t('share.chat.temporarySystemIssue')}
</div>
<div
className='flex items-center px-3 h-7 bg-white shadow-xs rounded-md text-xs font-medium text-gray-700 cursor-pointer'
onClick={handleReload}
>
{t('share.chat.tryToSolve')}
</div>
</div>
)
}
{
hasSetInputs && (
<div className={cn(doShowSuggestion ? 'pb-[140px]' : (isResponsing ? 'pb-[113px]' : 'pb-[76px]'), 'relative grow h-[200px] pc:w-[794px] max-w-full mobile:w-full mx-auto mb-3.5 overflow-hidden')}>

View File

@ -27,6 +27,8 @@ const translation = {
title: 'Delete conversation',
content: 'Are you sure you want to delete this conversation?',
},
tryToSolve: 'Try to solve',
temporarySystemIssue: 'Sorry, temporary system issue.',
},
generation: {
tabs: {

View File

@ -23,6 +23,8 @@ const translation = {
title: '删除对话',
content: '您确定要删除此对话吗?',
},
tryToSolve: '尝试解决',
temporarySystemIssue: '抱歉,临时系统问题。',
},
generation: {
tabs: {

View File

@ -28,12 +28,13 @@ export type IOnDataMoreInfo = {
taskId?: string
messageId: string
errorMessage?: string
errorCode?: string
}
export type IOnData = (message: string, isFirstMessage: boolean, moreInfo: IOnDataMoreInfo) => void
export type IOnThought = (though: ThoughtItem) => void
export type IOnCompleted = (hasError?: boolean) => void
export type IOnError = (msg: string) => void
export type IOnError = (msg: string, code?: string) => void
type IOtherOptions = {
isPublicAPI?: boolean
@ -102,6 +103,7 @@ const handleStream = (response: any, onData: IOnData, onCompleted?: IOnCompleted
conversationId: undefined,
messageId: '',
errorMessage: bufferObj.message,
errorCode: bufferObj.code,
})
hasError = true
onCompleted && onCompleted(true)
@ -345,7 +347,7 @@ export const ssePost = (url: string, fetchOptions: any, { isPublicAPI = false, o
return handleStream(res, (str: string, isFirstMessage: boolean, moreInfo: IOnDataMoreInfo) => {
if (moreInfo.errorMessage) {
// debugger
onError?.(moreInfo.errorMessage)
onError?.(moreInfo.errorMessage, moreInfo.errorCode)
if (moreInfo.errorMessage !== 'AbortError: The user aborted a request.')
Toast.notify({ type: 'error', message: moreInfo.errorMessage })
return