mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-12 20:29:02 +08:00
fix: stop response btn hide messages (#261)
This commit is contained in:
parent
91bcbd0b26
commit
5e772bd10b
@ -1,36 +1,36 @@
|
|||||||
'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> = ({
|
|||||||
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> = ({
|
|||||||
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> = ({
|
|||||||
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> = ({
|
|||||||
setConversationId(null)
|
setConversationId(null)
|
||||||
abortController?.abort()
|
abortController?.abort()
|
||||||
setResponsingFalse()
|
setResponsingFalse()
|
||||||
setChatList(introduction ? [{
|
setChatList(introduction
|
||||||
|
? [{
|
||||||
id: `${Date.now()}`,
|
id: `${Date.now()}`,
|
||||||
content: getIntroduction(),
|
content: getIntroduction(),
|
||||||
isAnswer: true,
|
isAnswer: true,
|
||||||
isOpeningStatement: true
|
isOpeningStatement: true,
|
||||||
}] : [])
|
}]
|
||||||
|
: [])
|
||||||
setIsShowSuggestion(false)
|
setIsShowSuggestion(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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> = ({
|
|||||||
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> = ({
|
|||||||
dataset: {
|
dataset: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
id,
|
id,
|
||||||
}
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const postModelConfig: BackendModelConfig = {
|
const postModelConfig: BackendModelConfig = {
|
||||||
@ -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> = ({
|
|||||||
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> = ({
|
|||||||
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> = ({
|
|||||||
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> = ({
|
|||||||
}, [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> = ({
|
|||||||
dataset: {
|
dataset: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
id,
|
id,
|
||||||
}
|
},
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const postModelConfig: BackendModelConfig = {
|
const postModelConfig: BackendModelConfig = {
|
||||||
@ -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> = ({
|
|||||||
},
|
},
|
||||||
onError() {
|
onError() {
|
||||||
setResponsingFalse()
|
setResponsingFalse()
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="shrink-0">
|
<div className="shrink-0">
|
||||||
@ -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
|
||||||
|
@ -1,40 +1,39 @@
|
|||||||
|
/* 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()
|
||||||
@ -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> = ({
|
|||||||
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> = ({
|
|||||||
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> = ({
|
|||||||
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,7 +129,8 @@ const Main: FC<IMainProps> = ({
|
|||||||
name: item?.name || '',
|
name: item?.name || '',
|
||||||
introduction: notSyncToStateIntroduction,
|
introduction: notSyncToStateIntroduction,
|
||||||
})
|
})
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
notSyncToStateInputs = newConversationInputs
|
notSyncToStateInputs = newConversationInputs
|
||||||
setCurrInputs(notSyncToStateInputs)
|
setCurrInputs(notSyncToStateInputs)
|
||||||
}
|
}
|
||||||
@ -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> = ({
|
|||||||
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> = ({
|
|||||||
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> = ({
|
|||||||
// 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,35 +212,36 @@ 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,
|
app_id: installedAppInfo?.id,
|
||||||
site: {
|
site: {
|
||||||
title: installedAppInfo?.app.name,
|
title: installedAppInfo?.app.name,
|
||||||
prompt_public: false,
|
prompt_public: false,
|
||||||
copyright: ''
|
copyright: '',
|
||||||
},
|
},
|
||||||
plan: 'basic',
|
plan: 'basic',
|
||||||
}: fetchAppInfo(), fetchConversations(isInstalledApp, installedAppInfo?.id), fetchAppParams(isInstalledApp, installedAppInfo?.id)])
|
|
||||||
}
|
}
|
||||||
|
: fetchAppInfo(), fetchConversations(isInstalledApp, installedAppInfo?.id), fetchAppParams(isInstalledApp, installedAppInfo?.id)])
|
||||||
|
}
|
||||||
|
|
||||||
// init
|
// init
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -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> = ({
|
|||||||
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> = ({
|
|||||||
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> = ({
|
|||||||
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> = ({
|
|||||||
},
|
},
|
||||||
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> = ({
|
|||||||
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)
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
@ -482,12 +482,14 @@ const Main: FC<IMainProps> = ({
|
|||||||
{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,7 +506,7 @@ 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
|
||||||
@ -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}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user