Unverified Commit 5e772bd1 authored by Joel's avatar Joel Committed by GitHub

fix: stop response btn hide messages (#261)

parent 91bcbd0b
'use client' 'use client'
import type { FC } from 'react' import type { FC } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import React, { useEffect, useState, useRef } from 'react' import React, { useEffect, useRef, useState } from 'react'
import cn from 'classnames' import cn from 'classnames'
import produce from 'immer' import produce from 'immer'
import { useBoolean, useGetState } from 'ahooks' import { useBoolean, useGetState } from 'ahooks'
import { useContext } from 'use-context-selector' import { useContext } from 'use-context-selector'
import dayjs from 'dayjs'
import HasNotSetAPIKEY from '../base/warning-mask/has-not-set-api'
import FormattingChanged from '../base/warning-mask/formatting-changed'
import GroupName from '../base/group-name'
import { AppType } from '@/types/app' import { AppType } from '@/types/app'
import PromptValuePanel, { replaceStringWithValues } from '@/app/components/app/configuration/prompt-value-panel' import PromptValuePanel, { replaceStringWithValues } from '@/app/components/app/configuration/prompt-value-panel'
import type { IChatItem } from '@/app/components/app/chat' import type { IChatItem } from '@/app/components/app/chat'
import Chat from '@/app/components/app/chat' import Chat from '@/app/components/app/chat'
import ConfigContext from '@/context/debug-configuration' import ConfigContext from '@/context/debug-configuration'
import { ToastContext } from '@/app/components/base/toast' import { ToastContext } from '@/app/components/base/toast'
import { sendChatMessage, sendCompletionMessage, fetchSuggestedQuestions, fetchConvesationMessages } from '@/service/debug' import { fetchConvesationMessages, fetchSuggestedQuestions, sendChatMessage, sendCompletionMessage } from '@/service/debug'
import Button from '@/app/components/base/button' import Button from '@/app/components/base/button'
import type { ModelConfig as BackendModelConfig } from '@/types/app' import type { ModelConfig as BackendModelConfig } from '@/types/app'
import { promptVariablesToUserInputsForm } from '@/utils/model-config' import { promptVariablesToUserInputsForm } from '@/utils/model-config'
import HasNotSetAPIKEY from '../base/warning-mask/has-not-set-api'
import FormattingChanged from '../base/warning-mask/formatting-changed'
import TextGeneration from '@/app/components/app/text-generate/item' import TextGeneration from '@/app/components/app/text-generate/item'
import GroupName from '../base/group-name'
import dayjs from 'dayjs'
import { IS_CE_EDITION } from '@/config' import { IS_CE_EDITION } from '@/config'
interface IDebug { type IDebug = {
hasSetAPIKEY: boolean hasSetAPIKEY: boolean
onSetting: () => void onSetting: () => void
} }
const Debug: FC<IDebug> = ({ const Debug: FC<IDebug> = ({
hasSetAPIKEY = true, hasSetAPIKEY = true,
onSetting onSetting,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const { const {
...@@ -51,14 +51,12 @@ const Debug: FC<IDebug> = ({ ...@@ -51,14 +51,12 @@ const Debug: FC<IDebug> = ({
completionParams, completionParams,
} = useContext(ConfigContext) } = useContext(ConfigContext)
const [chatList, setChatList, getChatList] = useGetState<IChatItem[]>([]) const [chatList, setChatList, getChatList] = useGetState<IChatItem[]>([])
const chatListDomRef = useRef<HTMLDivElement>(null) const chatListDomRef = useRef<HTMLDivElement>(null)
useEffect(() => { useEffect(() => {
// scroll to bottom // scroll to bottom
if (chatListDomRef.current) { if (chatListDomRef.current)
chatListDomRef.current.scrollTop = chatListDomRef.current.scrollHeight chatListDomRef.current.scrollTop = chatListDomRef.current.scrollHeight
}
}, [chatList]) }, [chatList])
const getIntroduction = () => replaceStringWithValues(introduction, modelConfig.configs.prompt_variables, inputs) const getIntroduction = () => replaceStringWithValues(introduction, modelConfig.configs.prompt_variables, inputs)
...@@ -68,7 +66,7 @@ const Debug: FC<IDebug> = ({ ...@@ -68,7 +66,7 @@ const Debug: FC<IDebug> = ({
id: `${Date.now()}`, id: `${Date.now()}`,
content: getIntroduction(), content: getIntroduction(),
isAnswer: true, isAnswer: true,
isOpeningStatement: true isOpeningStatement: true,
}]) }])
} }
}, [introduction, modelConfig.configs.prompt_variables, inputs]) }, [introduction, modelConfig.configs.prompt_variables, inputs])
...@@ -76,11 +74,12 @@ const Debug: FC<IDebug> = ({ ...@@ -76,11 +74,12 @@ const Debug: FC<IDebug> = ({
const [isResponsing, { setTrue: setResponsingTrue, setFalse: setResponsingFalse }] = useBoolean(false) const [isResponsing, { setTrue: setResponsingTrue, setFalse: setResponsingFalse }] = useBoolean(false)
const [abortController, setAbortController] = useState<AbortController | null>(null) const [abortController, setAbortController] = useState<AbortController | null>(null)
const [isShowFormattingChangeConfirm, setIsShowFormattingChangeConfirm] = useState(false) const [isShowFormattingChangeConfirm, setIsShowFormattingChangeConfirm] = useState(false)
const [isShowSuggestion, setIsShowSuggestion] = useState(false)
useEffect(() => { useEffect(() => {
if (formattingChanged && chatList.some(item => !item.isAnswer)) { if (formattingChanged && chatList.some(item => !item.isAnswer))
setIsShowFormattingChangeConfirm(true) setIsShowFormattingChangeConfirm(true)
}
setFormattingChanged(false) setFormattingChanged(false)
}, [formattingChanged]) }, [formattingChanged])
...@@ -88,12 +87,14 @@ const Debug: FC<IDebug> = ({ ...@@ -88,12 +87,14 @@ const Debug: FC<IDebug> = ({
setConversationId(null) setConversationId(null)
abortController?.abort() abortController?.abort()
setResponsingFalse() setResponsingFalse()
setChatList(introduction ? [{ setChatList(introduction
id: `${Date.now()}`, ? [{
content: getIntroduction(), id: `${Date.now()}`,
isAnswer: true, content: getIntroduction(),
isOpeningStatement: true isAnswer: true,
}] : []) isOpeningStatement: true,
}]
: [])
setIsShowSuggestion(false) setIsShowSuggestion(false)
} }
...@@ -119,12 +120,11 @@ const Debug: FC<IDebug> = ({ ...@@ -119,12 +120,11 @@ const Debug: FC<IDebug> = ({
}) // compatible with old version }) // compatible with old version
// debugger // debugger
requiredVars.forEach(({ key }) => { requiredVars.forEach(({ key }) => {
if (hasEmptyInput) { if (hasEmptyInput)
return return
}
if (!inputs[key]) { if (!inputs[key])
hasEmptyInput = true hasEmptyInput = true
}
}) })
if (hasEmptyInput) { if (hasEmptyInput) {
...@@ -134,7 +134,6 @@ const Debug: FC<IDebug> = ({ ...@@ -134,7 +134,6 @@ const Debug: FC<IDebug> = ({
return !hasEmptyInput return !hasEmptyInput
} }
const [isShowSuggestion, setIsShowSuggestion] = useState(false)
const doShowSuggestion = isShowSuggestion && !isResponsing const doShowSuggestion = isShowSuggestion && !isResponsing
const [suggestQuestions, setSuggestQuestions] = useState<string[]>([]) const [suggestQuestions, setSuggestQuestions] = useState<string[]>([])
const onSend = async (message: string) => { const onSend = async (message: string) => {
...@@ -147,7 +146,7 @@ const Debug: FC<IDebug> = ({ ...@@ -147,7 +146,7 @@ const Debug: FC<IDebug> = ({
dataset: { dataset: {
enabled: true, enabled: true,
id, id,
} },
})) }))
const postModelConfig: BackendModelConfig = { const postModelConfig: BackendModelConfig = {
...@@ -155,17 +154,17 @@ const Debug: FC<IDebug> = ({ ...@@ -155,17 +154,17 @@ const Debug: FC<IDebug> = ({
user_input_form: promptVariablesToUserInputsForm(modelConfig.configs.prompt_variables), user_input_form: promptVariablesToUserInputsForm(modelConfig.configs.prompt_variables),
opening_statement: introduction, opening_statement: introduction,
more_like_this: { more_like_this: {
enabled: false enabled: false,
}, },
suggested_questions_after_answer: suggestedQuestionsAfterAnswerConfig, suggested_questions_after_answer: suggestedQuestionsAfterAnswerConfig,
agent_mode: { agent_mode: {
enabled: true, enabled: true,
tools: [...postDatasets] tools: [...postDatasets],
}, },
model: { model: {
provider: modelConfig.provider, provider: modelConfig.provider,
name: modelConfig.model_id, name: modelConfig.model_id,
completion_params: completionParams as any completion_params: completionParams as any,
}, },
} }
...@@ -215,32 +214,32 @@ const Debug: FC<IDebug> = ({ ...@@ -215,32 +214,32 @@ const Debug: FC<IDebug> = ({
setConversationId(newConversationId) setConversationId(newConversationId)
_newConversationId = newConversationId _newConversationId = newConversationId
} }
if (messageId) { if (messageId)
responseItem.id = messageId responseItem.id = messageId
}
// closesure new list is outdated. // closesure new list is outdated.
const newListWithAnswer = produce( const newListWithAnswer = produce(
getChatList().filter(item => item.id !== responseItem.id && item.id !== placeholderAnswerId), getChatList().filter(item => item.id !== responseItem.id && item.id !== placeholderAnswerId),
(draft) => { (draft) => {
if (!draft.find(item => item.id === questionId)) { if (!draft.find(item => item.id === questionId))
draft.push({ ...questionItem }) draft.push({ ...questionItem })
}
draft.push({ ...responseItem }) draft.push({ ...responseItem })
}) })
setChatList(newListWithAnswer) setChatList(newListWithAnswer)
}, },
async onCompleted(hasError?: boolean) { async onCompleted(hasError?: boolean) {
setResponsingFalse() setResponsingFalse()
if (hasError) { if (hasError)
return return
}
if (_newConversationId) { if (_newConversationId) {
const { data }: any = await fetchConvesationMessages(appId, _newConversationId as string) const { data }: any = await fetchConvesationMessages(appId, _newConversationId as string)
const newResponseItem = data.find((item: any) => item.id === responseItem.id) const newResponseItem = data.find((item: any) => item.id === responseItem.id)
if (!newResponseItem) { if (!newResponseItem)
return return
}
setChatList(produce(getChatList(), draft => { setChatList(produce(getChatList(), (draft) => {
const index = draft.findIndex(item => item.id === responseItem.id) const index = draft.findIndex(item => item.id === responseItem.id)
if (index !== -1) { if (index !== -1) {
draft[index] = { draft[index] = {
...@@ -249,7 +248,7 @@ const Debug: FC<IDebug> = ({ ...@@ -249,7 +248,7 @@ const Debug: FC<IDebug> = ({
time: dayjs.unix(newResponseItem.created_at).format('hh:mm A'), time: dayjs.unix(newResponseItem.created_at).format('hh:mm A'),
tokens: newResponseItem.answer_tokens + newResponseItem.message_tokens, tokens: newResponseItem.answer_tokens + newResponseItem.message_tokens,
latency: newResponseItem.provider_response_latency.toFixed(2), latency: newResponseItem.provider_response_latency.toFixed(2),
} },
} }
} }
})) }))
...@@ -263,10 +262,10 @@ const Debug: FC<IDebug> = ({ ...@@ -263,10 +262,10 @@ const Debug: FC<IDebug> = ({
onError() { onError() {
setResponsingFalse() setResponsingFalse()
// role back placeholder answer // role back placeholder answer
setChatList(produce(getChatList(), draft => { setChatList(produce(getChatList(), (draft) => {
draft.splice(draft.findIndex(item => item.id === placeholderAnswerId), 1) draft.splice(draft.findIndex(item => item.id === placeholderAnswerId), 1)
})) }))
} },
}) })
return true return true
} }
...@@ -277,7 +276,7 @@ const Debug: FC<IDebug> = ({ ...@@ -277,7 +276,7 @@ const Debug: FC<IDebug> = ({
}, [controlClearChatMessage]) }, [controlClearChatMessage])
const [completionQuery, setCompletionQuery] = useState('') const [completionQuery, setCompletionQuery] = useState('')
const [completionRes, setCompletionRes] = useState(``) const [completionRes, setCompletionRes] = useState('')
const sendTextCompletion = async () => { const sendTextCompletion = async () => {
if (isResponsing) { if (isResponsing) {
...@@ -297,7 +296,7 @@ const Debug: FC<IDebug> = ({ ...@@ -297,7 +296,7 @@ const Debug: FC<IDebug> = ({
dataset: { dataset: {
enabled: true, enabled: true,
id, id,
} },
})) }))
const postModelConfig: BackendModelConfig = { const postModelConfig: BackendModelConfig = {
...@@ -308,16 +307,15 @@ const Debug: FC<IDebug> = ({ ...@@ -308,16 +307,15 @@ const Debug: FC<IDebug> = ({
more_like_this: moreLikeThisConifg, more_like_this: moreLikeThisConifg,
agent_mode: { agent_mode: {
enabled: true, enabled: true,
tools: [...postDatasets] tools: [...postDatasets],
}, },
model: { model: {
provider: modelConfig.provider, provider: modelConfig.provider,
name: modelConfig.model_id, name: modelConfig.model_id,
completion_params: completionParams as any completion_params: completionParams as any,
}, },
} }
const data = { const data = {
inputs, inputs,
query: completionQuery, query: completionQuery,
...@@ -338,11 +336,10 @@ const Debug: FC<IDebug> = ({ ...@@ -338,11 +336,10 @@ const Debug: FC<IDebug> = ({
}, },
onError() { onError() {
setResponsingFalse() setResponsingFalse()
} },
}) })
} }
return ( return (
<> <>
<div className="shrink-0"> <div className="shrink-0">
...@@ -368,7 +365,7 @@ const Debug: FC<IDebug> = ({ ...@@ -368,7 +365,7 @@ const Debug: FC<IDebug> = ({
{/* Chat */} {/* Chat */}
{mode === AppType.chat && ( {mode === AppType.chat && (
<div className="mt-[34px] h-full flex flex-col"> <div className="mt-[34px] h-full flex flex-col">
<div className={cn(doShowSuggestion ? 'pb-[140px]' : 'pb-[66px]', "relative mt-1.5 grow h-[200px] overflow-hidden")}> <div className={cn(doShowSuggestion ? 'pb-[140px]' : (isResponsing ? 'pb-[113px]' : 'pb-[66px]'), 'relative mt-1.5 grow h-[200px] overflow-hidden')}>
<div className="h-full overflow-y-auto" ref={chatListDomRef}> <div className="h-full overflow-y-auto" ref={chatListDomRef}>
{/* {JSON.stringify(chatList)} */} {/* {JSON.stringify(chatList)} */}
<Chat <Chat
......
/* eslint-disable @typescript-eslint/no-use-before-define */
'use client' 'use client'
import type { FC } from 'react' import type { FC } from 'react'
import React, { useEffect, useState, useRef } from 'react' import React, { useEffect, useRef, useState } from 'react'
import cn from 'classnames' import cn from 'classnames'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { useContext } from 'use-context-selector' import { useContext } from 'use-context-selector'
import produce from 'immer' import produce from 'immer'
import { useBoolean, useGetState } from 'ahooks' import { useBoolean, useGetState } from 'ahooks'
import AppUnavailable from '../../base/app-unavailable'
import useConversation from './hooks/use-conversation' import useConversation from './hooks/use-conversation'
import s from './style.module.css'
import { ToastContext } from '@/app/components/base/toast' import { ToastContext } from '@/app/components/base/toast'
import Sidebar from '@/app/components/share/chat/sidebar' import Sidebar from '@/app/components/share/chat/sidebar'
import ConfigSence from '@/app/components/share/chat/config-scence' import ConfigSence from '@/app/components/share/chat/config-scence'
import Header from '@/app/components/share/header' import Header from '@/app/components/share/header'
import { fetchAppInfo, fetchAppParams, fetchChatList, fetchConversations, sendChatMessage, updateFeedback, fetchSuggestedQuestions } from '@/service/share' import { fetchAppInfo, fetchAppParams, fetchChatList, fetchConversations, fetchSuggestedQuestions, sendChatMessage, updateFeedback } from '@/service/share'
import type { ConversationItem, SiteInfo } from '@/models/share' import type { ConversationItem, SiteInfo } from '@/models/share'
import type { PromptConfig } from '@/models/debug' 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'
import Chat from '@/app/components/app/chat' import Chat from '@/app/components/app/chat'
import { changeLanguage } from '@/i18n/i18next-config' import { changeLanguage } from '@/i18n/i18next-config'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import Loading from '@/app/components/base/loading' import Loading from '@/app/components/base/loading'
import { replaceStringWithValues } from '@/app/components/app/configuration/prompt-value-panel' import { replaceStringWithValues } from '@/app/components/app/configuration/prompt-value-panel'
import AppUnavailable from '../../base/app-unavailable'
import { userInputsFormToPromptVariables } from '@/utils/model-config' import { userInputsFormToPromptVariables } from '@/utils/model-config'
import { SuggestedQuestionsAfterAnswerConfig } from '@/models/debug' import type { InstalledApp } from '@/models/explore'
import { InstalledApp } from '@/models/explore'
import s from './style.module.css'
export type IMainProps = { export type IMainProps = {
isInstalledApp?: boolean, isInstalledApp?: boolean
installedAppInfo? : InstalledApp installedAppInfo?: InstalledApp
} }
const Main: FC<IMainProps> = ({ const Main: FC<IMainProps> = ({
isInstalledApp = false, isInstalledApp = false,
installedAppInfo installedAppInfo,
}) => { }) => {
const { t } = useTranslation() const { t } = useTranslation()
const media = useBreakpoints() const media = useBreakpoints()
...@@ -53,7 +52,7 @@ const Main: FC<IMainProps> = ({ ...@@ -53,7 +52,7 @@ const Main: FC<IMainProps> = ({
const [plan, setPlan] = useState<string>('basic') // basic/plus/pro const [plan, setPlan] = useState<string>('basic') // basic/plus/pro
// in mobile, show sidebar by click button // in mobile, show sidebar by click button
const [isShowSidebar, { setTrue: showSidebar, setFalse: hideSidebar }] = useBoolean(false) 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. // Can Use metadata(https://beta.nextjs.org/docs/api-reference/metadata) to set title. But it only works in server side client.
useEffect(() => { useEffect(() => {
if (siteInfo?.title) { if (siteInfo?.title) {
if (plan !== 'basic') if (plan !== 'basic')
...@@ -61,7 +60,6 @@ const Main: FC<IMainProps> = ({ ...@@ -61,7 +60,6 @@ const Main: FC<IMainProps> = ({
else else
document.title = `${siteInfo.title} - Powered by Dify` document.title = `${siteInfo.title} - Powered by Dify`
} }
}, [siteInfo?.title, plan]) }, [siteInfo?.title, plan])
/* /*
...@@ -81,7 +79,7 @@ const Main: FC<IMainProps> = ({ ...@@ -81,7 +79,7 @@ const Main: FC<IMainProps> = ({
resetNewConversationInputs, resetNewConversationInputs,
setCurrInputs, setCurrInputs,
setNewConversationInfo, setNewConversationInfo,
setExistConversationInfo setExistConversationInfo,
} = useConversation() } = useConversation()
const [hasMore, setHasMore] = useState<boolean>(false) const [hasMore, setHasMore] = useState<boolean>(false)
const onMoreLoaded = ({ data: conversations, has_more }: any) => { const onMoreLoaded = ({ data: conversations, has_more }: any) => {
...@@ -101,9 +99,9 @@ const Main: FC<IMainProps> = ({ ...@@ -101,9 +99,9 @@ const Main: FC<IMainProps> = ({
setChatList(generateNewChatListWithOpenstatement('', inputs)) setChatList(generateNewChatListWithOpenstatement('', inputs))
} }
const hasSetInputs = (() => { const hasSetInputs = (() => {
if (!isNewConversation) { if (!isNewConversation)
return true return true
}
return isChatStarted return isChatStarted
})() })()
...@@ -111,7 +109,8 @@ const Main: FC<IMainProps> = ({ ...@@ -111,7 +109,8 @@ const Main: FC<IMainProps> = ({
const conversationIntroduction = currConversationInfo?.introduction || '' const conversationIntroduction = currConversationInfo?.introduction || ''
const handleConversationSwitch = () => { const handleConversationSwitch = () => {
if (!inited) return if (!inited)
return
if (!appId) { if (!appId) {
// wait for appId // wait for appId
setTimeout(handleConversationSwitch, 100) setTimeout(handleConversationSwitch, 100)
...@@ -130,12 +129,13 @@ const Main: FC<IMainProps> = ({ ...@@ -130,12 +129,13 @@ const Main: FC<IMainProps> = ({
name: item?.name || '', name: item?.name || '',
introduction: notSyncToStateIntroduction, introduction: notSyncToStateIntroduction,
}) })
} else { }
else {
notSyncToStateInputs = newConversationInputs notSyncToStateInputs = newConversationInputs
setCurrInputs(notSyncToStateInputs) setCurrInputs(notSyncToStateInputs)
} }
// update chat list of current conversation // update chat list of current conversation
if (!isNewConversation && !conversationIdChangeBecauseOfNew && !isResponsing) { if (!isNewConversation && !conversationIdChangeBecauseOfNew && !isResponsing) {
fetchChatList(currConversationId, isInstalledApp, installedAppInfo?.id).then((res: any) => { fetchChatList(currConversationId, isInstalledApp, installedAppInfo?.id).then((res: any) => {
const { data } = res const { data } = res
...@@ -158,9 +158,8 @@ const Main: FC<IMainProps> = ({ ...@@ -158,9 +158,8 @@ const Main: FC<IMainProps> = ({
}) })
} }
if (isNewConversation && isChatStarted) { if (isNewConversation && isChatStarted)
setChatList(generateNewChatListWithOpenstatement()) setChatList(generateNewChatListWithOpenstatement())
}
setControlFocus(Date.now()) setControlFocus(Date.now())
} }
...@@ -170,7 +169,8 @@ const Main: FC<IMainProps> = ({ ...@@ -170,7 +169,8 @@ const Main: FC<IMainProps> = ({
if (id === '-1') { if (id === '-1') {
createNewChat() createNewChat()
setConversationIdChangeBecauseOfNew(true) setConversationIdChangeBecauseOfNew(true)
} else { }
else {
setConversationIdChangeBecauseOfNew(false) setConversationIdChangeBecauseOfNew(false)
} }
// trigger handleConversationSwitch // trigger handleConversationSwitch
...@@ -186,9 +186,8 @@ const Main: FC<IMainProps> = ({ ...@@ -186,9 +186,8 @@ const Main: FC<IMainProps> = ({
const chatListDomRef = useRef<HTMLDivElement>(null) const chatListDomRef = useRef<HTMLDivElement>(null)
useEffect(() => { useEffect(() => {
// scroll to bottom // scroll to bottom
if (chatListDomRef.current) { if (chatListDomRef.current)
chatListDomRef.current.scrollTop = chatListDomRef.current.scrollHeight chatListDomRef.current.scrollTop = chatListDomRef.current.scrollHeight
}
}, [chatList, currConversationId]) }, [chatList, currConversationId])
// user can not edit inputs if user had send message // user can not edit inputs if user had send message
const canEditInpus = !chatList.some(item => item.isAnswer === false) && isNewConversation const canEditInpus = !chatList.some(item => item.isAnswer === false) && isNewConversation
...@@ -196,15 +195,15 @@ const Main: FC<IMainProps> = ({ ...@@ -196,15 +195,15 @@ const Main: FC<IMainProps> = ({
// if new chat is already exist, do not create new chat // if new chat is already exist, do not create new chat
abortController?.abort() abortController?.abort()
setResponsingFalse() setResponsingFalse()
if (conversationList.some(item => item.id === '-1')) { if (conversationList.some(item => item.id === '-1'))
return return
}
setConversationList(produce(conversationList, draft => { setConversationList(produce(conversationList, (draft) => {
draft.unshift({ draft.unshift({
id: '-1', id: '-1',
name: t('share.chat.newChatDefaultName'), name: t('share.chat.newChatDefaultName'),
inputs: newConversationInputs, inputs: newConversationInputs,
introduction: conversationIntroduction introduction: conversationIntroduction,
}) })
})) }))
} }
...@@ -213,36 +212,37 @@ const Main: FC<IMainProps> = ({ ...@@ -213,36 +212,37 @@ const Main: FC<IMainProps> = ({
const generateNewChatListWithOpenstatement = (introduction?: string, inputs?: Record<string, any> | null) => { const generateNewChatListWithOpenstatement = (introduction?: string, inputs?: Record<string, any> | null) => {
let caculatedIntroduction = introduction || conversationIntroduction || '' let caculatedIntroduction = introduction || conversationIntroduction || ''
const caculatedPromptVariables = inputs || currInputs || null const caculatedPromptVariables = inputs || currInputs || null
if (caculatedIntroduction && caculatedPromptVariables) { if (caculatedIntroduction && caculatedPromptVariables)
caculatedIntroduction = replaceStringWithValues(caculatedIntroduction, promptConfig?.prompt_variables || [], caculatedPromptVariables) caculatedIntroduction = replaceStringWithValues(caculatedIntroduction, promptConfig?.prompt_variables || [], caculatedPromptVariables)
}
// console.log(isPublicVersion) // console.log(isPublicVersion)
const openstatement = { const openstatement = {
id: `${Date.now()}`, id: `${Date.now()}`,
content: caculatedIntroduction, content: caculatedIntroduction,
isAnswer: true, isAnswer: true,
feedbackDisabled: true, feedbackDisabled: true,
isOpeningStatement: isPublicVersion isOpeningStatement: isPublicVersion,
} }
if (caculatedIntroduction) { if (caculatedIntroduction)
return [openstatement] return [openstatement]
}
return [] return []
} }
const fetchInitData = () => { const fetchInitData = () => {
return Promise.all([isInstalledApp ? { return Promise.all([isInstalledApp
app_id: installedAppInfo?.id, ? {
site: { app_id: installedAppInfo?.id,
title: installedAppInfo?.app.name, site: {
prompt_public: false, title: installedAppInfo?.app.name,
copyright: '' prompt_public: false,
}, copyright: '',
plan: 'basic', },
}: fetchAppInfo(), fetchConversations(isInstalledApp, installedAppInfo?.id), fetchAppParams(isInstalledApp, installedAppInfo?.id)]) plan: 'basic',
}
: fetchAppInfo(), fetchConversations(isInstalledApp, installedAppInfo?.id), fetchAppParams(isInstalledApp, installedAppInfo?.id)])
} }
// init // init
useEffect(() => { useEffect(() => {
(async () => { (async () => {
...@@ -255,16 +255,16 @@ const Main: FC<IMainProps> = ({ ...@@ -255,16 +255,16 @@ const Main: FC<IMainProps> = ({
setIsPublicVersion(tempIsPublicVersion) setIsPublicVersion(tempIsPublicVersion)
const prompt_template = '' const prompt_template = ''
// handle current conversation id // handle current conversation id
const { data: conversations, has_more } = conversationData as { data: ConversationItem[], has_more: boolean } const { data: conversations, has_more } = conversationData as { data: ConversationItem[]; has_more: boolean }
const _conversationId = getConversationIdFromStorage(appId) const _conversationId = getConversationIdFromStorage(appId)
const isNotNewConversation = conversations.some(item => item.id === _conversationId) const isNotNewConversation = conversations.some(item => item.id === _conversationId)
setHasMore(has_more) setHasMore(has_more)
// fetch new conversation info // fetch new conversation info
const { user_input_form, opening_statement: introduction, suggested_questions_after_answer }: any = appParams const { user_input_form, opening_statement: introduction, suggested_questions_after_answer }: any = appParams
const prompt_variables = userInputsFormToPromptVariables(user_input_form) const prompt_variables = userInputsFormToPromptVariables(user_input_form)
if(siteInfo.default_language) { if (siteInfo.default_language)
changeLanguage(siteInfo.default_language) changeLanguage(siteInfo.default_language)
}
setNewConversationInfo({ setNewConversationInfo({
name: t('share.chat.newChatDefaultName'), name: t('share.chat.newChatDefaultName'),
introduction, introduction,
...@@ -272,20 +272,22 @@ const Main: FC<IMainProps> = ({ ...@@ -272,20 +272,22 @@ const Main: FC<IMainProps> = ({
setSiteInfo(siteInfo as SiteInfo) setSiteInfo(siteInfo as SiteInfo)
setPromptConfig({ setPromptConfig({
prompt_template, prompt_template,
prompt_variables: prompt_variables, prompt_variables,
} as PromptConfig) } as PromptConfig)
setSuggestedQuestionsAfterAnswerConfig(suggested_questions_after_answer) setSuggestedQuestionsAfterAnswerConfig(suggested_questions_after_answer)
setConversationList(conversations as ConversationItem[]) setConversationList(conversations as ConversationItem[])
if (isNotNewConversation) { if (isNotNewConversation)
setCurrConversationId(_conversationId, appId, false) setCurrConversationId(_conversationId, appId, false)
}
setInited(true) setInited(true)
} catch (e: any) { }
catch (e: any) {
if (e.status === 404) { if (e.status === 404) {
setAppUnavailable(true) setAppUnavailable(true)
} else { }
else {
setIsUnknwonReason(true) setIsUnknwonReason(true)
setAppUnavailable(true) setAppUnavailable(true)
} }
...@@ -303,21 +305,20 @@ const Main: FC<IMainProps> = ({ ...@@ -303,21 +305,20 @@ const Main: FC<IMainProps> = ({
const checkCanSend = () => { const checkCanSend = () => {
const prompt_variables = promptConfig?.prompt_variables const prompt_variables = promptConfig?.prompt_variables
const inputs = currInputs const inputs = currInputs
if (!inputs || !prompt_variables || prompt_variables?.length === 0) { if (!inputs || !prompt_variables || prompt_variables?.length === 0)
return true return true
}
let hasEmptyInput = false let hasEmptyInput = false
const requiredVars = prompt_variables?.filter(({ key, name, required }) => { const requiredVars = prompt_variables?.filter(({ key, name, required }) => {
const res = (!key || !key.trim()) || (!name || !name.trim()) || (required || required === undefined || required === null) const res = (!key || !key.trim()) || (!name || !name.trim()) || (required || required === undefined || required === null)
return res return res
}) || [] // compatible with old version }) || [] // compatible with old version
requiredVars.forEach(({ key }) => { requiredVars.forEach(({ key }) => {
if (hasEmptyInput) { if (hasEmptyInput)
return return
}
if (!inputs?.[key]) { if (!inputs?.[key])
hasEmptyInput = true hasEmptyInput = true
}
}) })
if (hasEmptyInput) { if (hasEmptyInput) {
...@@ -378,9 +379,8 @@ const Main: FC<IMainProps> = ({ ...@@ -378,9 +379,8 @@ const Main: FC<IMainProps> = ({
onData: (message: string, isFirstMessage: boolean, { conversationId: newConversationId, messageId }: any) => { onData: (message: string, isFirstMessage: boolean, { conversationId: newConversationId, messageId }: any) => {
responseItem.content = responseItem.content + message responseItem.content = responseItem.content + message
responseItem.id = messageId responseItem.id = messageId
if (isFirstMessage && newConversationId) { if (isFirstMessage && newConversationId)
tempNewConversationId = newConversationId tempNewConversationId = newConversationId
}
// closesure new list is outdated. // closesure new list is outdated.
const newListWithAnswer = produce( const newListWithAnswer = produce(
...@@ -395,9 +395,9 @@ const Main: FC<IMainProps> = ({ ...@@ -395,9 +395,9 @@ const Main: FC<IMainProps> = ({
}, },
async onCompleted(hasError?: boolean) { async onCompleted(hasError?: boolean) {
setResponsingFalse() setResponsingFalse()
if (hasError) { if (hasError)
return return
}
let currChatList = conversationList let currChatList = conversationList
if (getConversationIdChangeBecauseOfNew()) { if (getConversationIdChangeBecauseOfNew()) {
const { data: conversations, has_more }: any = await fetchConversations(isInstalledApp, installedAppInfo?.id) const { data: conversations, has_more }: any = await fetchConversations(isInstalledApp, installedAppInfo?.id)
...@@ -418,7 +418,7 @@ const Main: FC<IMainProps> = ({ ...@@ -418,7 +418,7 @@ const Main: FC<IMainProps> = ({
onError() { onError() {
setResponsingFalse() setResponsingFalse()
// role back placeholder answer // role back placeholder answer
setChatList(produce(getChatList(), draft => { setChatList(produce(getChatList(), (draft) => {
draft.splice(draft.findIndex(item => item.id === placeholderAnswerId), 1) draft.splice(draft.findIndex(item => item.id === placeholderAnswerId), 1)
})) }))
}, },
...@@ -476,18 +476,20 @@ const Main: FC<IMainProps> = ({ ...@@ -476,18 +476,20 @@ const Main: FC<IMainProps> = ({
onCreateNewChat={() => handleConversationIdChange('-1')} onCreateNewChat={() => handleConversationIdChange('-1')}
/> />
)} )}
{/* {isNewConversation ? 'new' : 'exist'} {/* {isNewConversation ? 'new' : 'exist'}
{JSON.stringify(newConversationInputs ? newConversationInputs : {})} {JSON.stringify(newConversationInputs ? newConversationInputs : {})}
{JSON.stringify(existConversationInputs ? existConversationInputs : {})} */} {JSON.stringify(existConversationInputs ? existConversationInputs : {})} */}
<div <div
className={cn( className={cn(
"flex rounded-t-2xl bg-white overflow-hidden", 'flex rounded-t-2xl bg-white overflow-hidden',
isInstalledApp && 'rounded-b-2xl', isInstalledApp && 'rounded-b-2xl',
)} )}
style={isInstalledApp ? { style={isInstalledApp
boxShadow: '0px 12px 16px -4px rgba(16, 24, 40, 0.08), 0px 4px 6px -2px rgba(16, 24, 40, 0.03)' ? {
} : {}} boxShadow: '0px 12px 16px -4px rgba(16, 24, 40, 0.08), 0px 4px 6px -2px rgba(16, 24, 40, 0.03)',
}
: {}}
> >
{/* sidebar */} {/* sidebar */}
{!isMobile && renderSidebar()} {!isMobile && renderSidebar()}
...@@ -504,8 +506,8 @@ const Main: FC<IMainProps> = ({ ...@@ -504,8 +506,8 @@ const Main: FC<IMainProps> = ({
{/* main */} {/* main */}
<div className={cn( <div className={cn(
isInstalledApp ? s.installedApp : 'h-[calc(100vh_-_3rem)]', isInstalledApp ? s.installedApp : 'h-[calc(100vh_-_3rem)]',
'flex-grow flex flex-col overflow-y-auto' 'flex-grow flex flex-col overflow-y-auto',
) )
}> }>
<ConfigSence <ConfigSence
conversationName={conversationName} conversationName={conversationName}
...@@ -522,7 +524,7 @@ const Main: FC<IMainProps> = ({ ...@@ -522,7 +524,7 @@ const Main: FC<IMainProps> = ({
{ {
hasSetInputs && ( hasSetInputs && (
<div className={cn(doShowSuggestion ? 'pb-[140px]' : 'pb-[66px]', 'relative grow h-[200px] pc:w-[794px] max-w-full mobile:w-full mx-auto mb-3.5 overflow-hidden')}> <div className={cn(doShowSuggestion ? 'pb-[140px]' : (isResponsing ? 'pb-[113px]' : 'pb-[66px]'), 'relative grow h-[200px] pc:w-[794px] max-w-full mobile:w-full mx-auto mb-3.5 overflow-hidden')}>
<div className='h-full overflow-y-auto' ref={chatListDomRef}> <div className='h-full overflow-y-auto' ref={chatListDomRef}>
<Chat <Chat
chatList={chatList} chatList={chatList}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment