mirror of
https://github.com/langgenius/webapp-conversation.git
synced 2026-02-03 00:55:29 +08:00
Compare commits
6 Commits
fix/option
...
chore/hide
| Author | SHA1 | Date | |
|---|---|---|---|
| 5a85f0d427 | |||
| 96bd12af44 | |||
| 484a5dc102 | |||
| 10eb176f72 | |||
| f6b4b4a361 | |||
| f7ff288ff1 |
@ -4,25 +4,25 @@ import React from 'react'
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
|
|
||||||
type IAppUnavailableProps = {
|
type IAppUnavailableProps = {
|
||||||
isUnknwonReason: boolean
|
isUnknownReason: boolean
|
||||||
errMessage?: string
|
errMessage?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const AppUnavailable: FC<IAppUnavailableProps> = ({
|
const AppUnavailable: FC<IAppUnavailableProps> = ({
|
||||||
isUnknwonReason,
|
isUnknownReason,
|
||||||
errMessage,
|
errMessage,
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
let message = errMessage
|
let message = errMessage
|
||||||
if (!errMessage)
|
if (!errMessage)
|
||||||
message = (isUnknwonReason ? t('app.common.appUnkonwError') : t('app.common.appUnavailable')) as string
|
message = (isUnknownReason ? t('app.common.appUnkonwError') : t('app.common.appUnavailable')) as string
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex items-center justify-center w-screen h-screen'>
|
<div className='flex items-center justify-center w-screen h-screen'>
|
||||||
<h1 className='mr-5 h-[50px] leading-[50px] pr-5 text-[24px] font-medium'
|
<h1 className='mr-5 h-[50px] leading-[50px] pr-5 text-[24px] font-medium'
|
||||||
style={{
|
style={{
|
||||||
borderRight: '1px solid rgba(0,0,0,.3)',
|
borderRight: '1px solid rgba(0,0,0,.3)',
|
||||||
}}>{(errMessage || isUnknwonReason) ? 500 : 404}</h1>
|
}}>{(errMessage || isUnknownReason) ? 500 : 404}</h1>
|
||||||
<div className='text-sm'>{message}</div>
|
<div className='text-sm'>{message}</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -58,7 +58,7 @@ type IAnswerProps = {
|
|||||||
item: ChatItem
|
item: ChatItem
|
||||||
feedbackDisabled: boolean
|
feedbackDisabled: boolean
|
||||||
onFeedback?: FeedbackFunc
|
onFeedback?: FeedbackFunc
|
||||||
isResponsing?: boolean
|
isResponding?: boolean
|
||||||
allToolIcons?: Record<string, string | Emoji>
|
allToolIcons?: Record<string, string | Emoji>
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ const Answer: FC<IAnswerProps> = ({
|
|||||||
item,
|
item,
|
||||||
feedbackDisabled = false,
|
feedbackDisabled = false,
|
||||||
onFeedback,
|
onFeedback,
|
||||||
isResponsing,
|
isResponding,
|
||||||
allToolIcons,
|
allToolIcons,
|
||||||
}) => {
|
}) => {
|
||||||
const { id, content, feedback, agent_thoughts, workflowProcess } = item
|
const { id, content, feedback, agent_thoughts, workflowProcess } = item
|
||||||
@ -153,7 +153,7 @@ const Answer: FC<IAnswerProps> = ({
|
|||||||
<Thought
|
<Thought
|
||||||
thought={item}
|
thought={item}
|
||||||
allToolIcons={allToolIcons || {}}
|
allToolIcons={allToolIcons || {}}
|
||||||
isFinished={!!item.observation || !isResponsing}
|
isFinished={!!item.observation || !isResponding}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ const Answer: FC<IAnswerProps> = ({
|
|||||||
<div key={id}>
|
<div key={id}>
|
||||||
<div className='flex items-start'>
|
<div className='flex items-start'>
|
||||||
<div className={`${s.answerIcon} w-10 h-10 shrink-0`}>
|
<div className={`${s.answerIcon} w-10 h-10 shrink-0`}>
|
||||||
{isResponsing
|
{isResponding
|
||||||
&& <div className={s.typeingIcon}>
|
&& <div className={s.typeingIcon}>
|
||||||
<LoadingAnim type='avatar' />
|
<LoadingAnim type='avatar' />
|
||||||
</div>
|
</div>
|
||||||
@ -181,7 +181,7 @@ const Answer: FC<IAnswerProps> = ({
|
|||||||
{workflowProcess && (
|
{workflowProcess && (
|
||||||
<WorkflowProcess data={workflowProcess} hideInfo />
|
<WorkflowProcess data={workflowProcess} hideInfo />
|
||||||
)}
|
)}
|
||||||
{(isResponsing && (isAgentMode ? (!content && (agent_thoughts || []).filter(item => !!item.thought || !!item.tool).length === 0) : !content))
|
{(isResponding && (isAgentMode ? (!content && (agent_thoughts || []).filter(item => !!item.thought || !!item.tool).length === 0) : !content))
|
||||||
? (
|
? (
|
||||||
<div className='flex items-center justify-center w-6 h-5'>
|
<div className='flex items-center justify-center w-6 h-5'>
|
||||||
<LoadingAnim type='text' />
|
<LoadingAnim type='text' />
|
||||||
|
|||||||
@ -30,7 +30,7 @@ export type IChatProps = {
|
|||||||
checkCanSend?: () => boolean
|
checkCanSend?: () => boolean
|
||||||
onSend?: (message: string, files: VisionFile[]) => void
|
onSend?: (message: string, files: VisionFile[]) => void
|
||||||
useCurrentUserAvatar?: boolean
|
useCurrentUserAvatar?: boolean
|
||||||
isResponsing?: boolean
|
isResponding?: boolean
|
||||||
controlClearQuery?: number
|
controlClearQuery?: number
|
||||||
visionConfig?: VisionSettings
|
visionConfig?: VisionSettings
|
||||||
}
|
}
|
||||||
@ -43,7 +43,7 @@ const Chat: FC<IChatProps> = ({
|
|||||||
checkCanSend,
|
checkCanSend,
|
||||||
onSend = () => { },
|
onSend = () => { },
|
||||||
useCurrentUserAvatar,
|
useCurrentUserAvatar,
|
||||||
isResponsing,
|
isResponding,
|
||||||
controlClearQuery,
|
controlClearQuery,
|
||||||
visionConfig,
|
visionConfig,
|
||||||
}) => {
|
}) => {
|
||||||
@ -95,7 +95,7 @@ const Chat: FC<IChatProps> = ({
|
|||||||
if (!files.find(item => item.type === TransferMethod.local_file && !item.fileId)) {
|
if (!files.find(item => item.type === TransferMethod.local_file && !item.fileId)) {
|
||||||
if (files.length)
|
if (files.length)
|
||||||
onClear()
|
onClear()
|
||||||
if (!isResponsing)
|
if (!isResponding)
|
||||||
setQuery('')
|
setQuery('')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,7 +129,7 @@ const Chat: FC<IChatProps> = ({
|
|||||||
item={item}
|
item={item}
|
||||||
feedbackDisabled={feedbackDisabled}
|
feedbackDisabled={feedbackDisabled}
|
||||||
onFeedback={onFeedback}
|
onFeedback={onFeedback}
|
||||||
isResponsing={isResponsing && isLast}
|
isResponding={isResponding && isLast}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -33,7 +33,7 @@ const Main: FC = () => {
|
|||||||
* app info
|
* app info
|
||||||
*/
|
*/
|
||||||
const [appUnavailable, setAppUnavailable] = useState<boolean>(false)
|
const [appUnavailable, setAppUnavailable] = useState<boolean>(false)
|
||||||
const [isUnknwonReason, setIsUnknwonReason] = useState<boolean>(false)
|
const [isUnknownReason, setIsUnknownReason] = useState<boolean>(false)
|
||||||
const [promptConfig, setPromptConfig] = useState<PromptConfig | null>(null)
|
const [promptConfig, setPromptConfig] = useState<PromptConfig | null>(null)
|
||||||
const [inited, setInited] = useState<boolean>(false)
|
const [inited, setInited] = useState<boolean>(false)
|
||||||
// in mobile, show sidebar by click button
|
// in mobile, show sidebar by click button
|
||||||
@ -86,7 +86,7 @@ const Main: FC = () => {
|
|||||||
setCurrInputs(inputs)
|
setCurrInputs(inputs)
|
||||||
setChatStarted()
|
setChatStarted()
|
||||||
// parse variables in introduction
|
// parse variables in introduction
|
||||||
setChatList(generateNewChatListWithOpenstatement('', inputs))
|
setChatList(generateNewChatListWithOpenStatement('', inputs))
|
||||||
}
|
}
|
||||||
const hasSetInputs = (() => {
|
const hasSetInputs = (() => {
|
||||||
if (!isNewConversation)
|
if (!isNewConversation)
|
||||||
@ -121,10 +121,10 @@ const Main: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// update chat list of current conversation
|
// update chat list of current conversation
|
||||||
if (!isNewConversation && !conversationIdChangeBecauseOfNew && !isResponsing) {
|
if (!isNewConversation && !conversationIdChangeBecauseOfNew && !isResponding) {
|
||||||
fetchChatList(currConversationId).then((res: any) => {
|
fetchChatList(currConversationId).then((res: any) => {
|
||||||
const { data } = res
|
const { data } = res
|
||||||
const newChatList: ChatItem[] = generateNewChatListWithOpenstatement(notSyncToStateIntroduction, notSyncToStateInputs)
|
const newChatList: ChatItem[] = generateNewChatListWithOpenStatement(notSyncToStateIntroduction, notSyncToStateInputs)
|
||||||
|
|
||||||
data.forEach((item: any) => {
|
data.forEach((item: any) => {
|
||||||
newChatList.push({
|
newChatList.push({
|
||||||
@ -148,7 +148,7 @@ const Main: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isNewConversation && isChatStarted)
|
if (isNewConversation && isChatStarted)
|
||||||
setChatList(generateNewChatListWithOpenstatement())
|
setChatList(generateNewChatListWithOpenStatement())
|
||||||
}
|
}
|
||||||
useEffect(handleConversationSwitch, [currConversationId, inited])
|
useEffect(handleConversationSwitch, [currConversationId, inited])
|
||||||
|
|
||||||
@ -176,7 +176,7 @@ const Main: FC = () => {
|
|||||||
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 canEditInputs = !chatList.some(item => item.isAnswer === false) && isNewConversation
|
||||||
const createNewChat = () => {
|
const createNewChat = () => {
|
||||||
// if new chat is already exist, do not create new chat
|
// if new chat is already exist, do not create new chat
|
||||||
if (conversationList.some(item => item.id === '-1'))
|
if (conversationList.some(item => item.id === '-1'))
|
||||||
@ -193,21 +193,21 @@ const Main: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sometime introduction is not applied to state
|
// sometime introduction is not applied to state
|
||||||
const generateNewChatListWithOpenstatement = (introduction?: string, inputs?: Record<string, any> | null) => {
|
const generateNewChatListWithOpenStatement = (introduction?: string, inputs?: Record<string, any> | null) => {
|
||||||
let caculatedIntroduction = introduction || conversationIntroduction || ''
|
let calculatedIntroduction = introduction || conversationIntroduction || ''
|
||||||
const caculatedPromptVariables = inputs || currInputs || null
|
const calculatedPromptVariables = inputs || currInputs || null
|
||||||
if (caculatedIntroduction && caculatedPromptVariables)
|
if (calculatedIntroduction && calculatedPromptVariables)
|
||||||
caculatedIntroduction = replaceVarWithValues(caculatedIntroduction, promptConfig?.prompt_variables || [], caculatedPromptVariables)
|
calculatedIntroduction = replaceVarWithValues(calculatedIntroduction, promptConfig?.prompt_variables || [], calculatedPromptVariables)
|
||||||
|
|
||||||
const openstatement = {
|
const openstatement = {
|
||||||
id: `${Date.now()}`,
|
id: `${Date.now()}`,
|
||||||
content: caculatedIntroduction,
|
content: calculatedIntroduction,
|
||||||
isAnswer: true,
|
isAnswer: true,
|
||||||
feedbackDisabled: true,
|
feedbackDisabled: true,
|
||||||
isOpeningStatement: isShowPrompt,
|
isOpeningStatement: isShowPrompt,
|
||||||
}
|
}
|
||||||
if (caculatedIntroduction)
|
if (calculatedIntroduction)
|
||||||
return [openstatement]
|
return [openStatement]
|
||||||
|
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
@ -255,14 +255,14 @@ const Main: FC = () => {
|
|||||||
setAppUnavailable(true)
|
setAppUnavailable(true)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setIsUnknwonReason(true)
|
setIsUnknownReason(true)
|
||||||
setAppUnavailable(true)
|
setAppUnavailable(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})()
|
})()
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const [isResponsing, { setTrue: setResponsingTrue, setFalse: setResponsingFalse }] = useBoolean(false)
|
const [isResponding, { setTrue: setRespondingTrue, setFalse: setRespondingFalse }] = useBoolean(false)
|
||||||
const [abortController, setAbortController] = useState<AbortController | null>(null)
|
const [abortController, setAbortController] = useState<AbortController | null>(null)
|
||||||
const { notify } = Toast
|
const { notify } = Toast
|
||||||
const logError = (message: string) => {
|
const logError = (message: string) => {
|
||||||
@ -279,8 +279,8 @@ const Main: FC = () => {
|
|||||||
const inputLens = Object.values(currInputs).length
|
const inputLens = Object.values(currInputs).length
|
||||||
const promptVariablesLens = promptConfig.prompt_variables.length
|
const promptVariablesLens = promptConfig.prompt_variables.length
|
||||||
|
|
||||||
const emytyInput = inputLens < promptVariablesLens || Object.values(currInputs).find(v => !v)
|
const emptyInput = inputLens < promptVariablesLens || Object.values(currInputs).find(v => !v)
|
||||||
if (emytyInput) {
|
if (emptyInput) {
|
||||||
logError(t('app.errorMessage.valueOfVarRequired'))
|
logError(t('app.errorMessage.valueOfVarRequired'))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -291,7 +291,7 @@ const Main: FC = () => {
|
|||||||
const [openingSuggestedQuestions, setOpeningSuggestedQuestions] = useState<string[]>([])
|
const [openingSuggestedQuestions, setOpeningSuggestedQuestions] = useState<string[]>([])
|
||||||
const [messageTaskId, setMessageTaskId] = useState('')
|
const [messageTaskId, setMessageTaskId] = useState('')
|
||||||
const [hasStopResponded, setHasStopResponded, getHasStopResponded] = useGetState(false)
|
const [hasStopResponded, setHasStopResponded, getHasStopResponded] = useGetState(false)
|
||||||
const [isResponsingConIsCurrCon, setIsResponsingConCurrCon, getIsResponsingConIsCurrCon] = useGetState(true)
|
const [isRespondingConIsCurrCon, setIsRespondingConCurrCon, getIsRespondingConIsCurrCon] = useGetState(true)
|
||||||
const [userQuery, setUserQuery] = useState('')
|
const [userQuery, setUserQuery] = useState('')
|
||||||
|
|
||||||
const updateCurrentQA = ({
|
const updateCurrentQA = ({
|
||||||
@ -318,7 +318,7 @@ const Main: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const handleSend = async (message: string, files?: VisionFile[]) => {
|
const handleSend = async (message: string, files?: VisionFile[]) => {
|
||||||
if (isResponsing) {
|
if (isResponding) {
|
||||||
notify({ type: 'info', message: t('app.errorMessage.waitForResponse') })
|
notify({ type: 'info', message: t('app.errorMessage.waitForResponse') })
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -340,7 +340,7 @@ const Main: FC = () => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// qustion
|
// question
|
||||||
const questionId = `question-${Date.now()}`
|
const questionId = `question-${Date.now()}`
|
||||||
const questionItem = {
|
const questionItem = {
|
||||||
id: questionId,
|
id: questionId,
|
||||||
@ -374,7 +374,7 @@ const Main: FC = () => {
|
|||||||
const prevTempNewConversationId = getCurrConversationId() || '-1'
|
const prevTempNewConversationId = getCurrConversationId() || '-1'
|
||||||
let tempNewConversationId = ''
|
let tempNewConversationId = ''
|
||||||
|
|
||||||
setResponsingTrue()
|
setRespondingTrue()
|
||||||
sendChatMessage(data, {
|
sendChatMessage(data, {
|
||||||
getAbortController: (abortController) => {
|
getAbortController: (abortController) => {
|
||||||
setAbortController(abortController)
|
setAbortController(abortController)
|
||||||
@ -399,7 +399,7 @@ const Main: FC = () => {
|
|||||||
setMessageTaskId(taskId)
|
setMessageTaskId(taskId)
|
||||||
// has switched to other conversation
|
// has switched to other conversation
|
||||||
if (prevTempNewConversationId !== getCurrConversationId()) {
|
if (prevTempNewConversationId !== getCurrConversationId()) {
|
||||||
setIsResponsingConCurrCon(false)
|
setIsRespondingConCurrCon(false)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
updateCurrentQA({
|
updateCurrentQA({
|
||||||
@ -426,7 +426,7 @@ const Main: FC = () => {
|
|||||||
resetNewConversationInputs()
|
resetNewConversationInputs()
|
||||||
setChatNotStarted()
|
setChatNotStarted()
|
||||||
setCurrConversationId(tempNewConversationId, APP_ID, true)
|
setCurrConversationId(tempNewConversationId, APP_ID, true)
|
||||||
setResponsingFalse()
|
setRespondingFalse()
|
||||||
},
|
},
|
||||||
onFile(file) {
|
onFile(file) {
|
||||||
const lastThought = responseItem.agent_thoughts?.[responseItem.agent_thoughts?.length - 1]
|
const lastThought = responseItem.agent_thoughts?.[responseItem.agent_thoughts?.length - 1]
|
||||||
@ -465,7 +465,7 @@ const Main: FC = () => {
|
|||||||
}
|
}
|
||||||
// has switched to other conversation
|
// has switched to other conversation
|
||||||
if (prevTempNewConversationId !== getCurrConversationId()) {
|
if (prevTempNewConversationId !== getCurrConversationId()) {
|
||||||
setIsResponsingConCurrCon(false)
|
setIsRespondingConCurrCon(false)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -520,7 +520,7 @@ const Main: FC = () => {
|
|||||||
))
|
))
|
||||||
},
|
},
|
||||||
onError() {
|
onError() {
|
||||||
setResponsingFalse()
|
setRespondingFalse()
|
||||||
// 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)
|
||||||
@ -604,7 +604,7 @@ const Main: FC = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (appUnavailable)
|
if (appUnavailable)
|
||||||
return <AppUnavailable isUnknwonReason={isUnknwonReason} errMessage={!hasSetAppConfig ? 'Please set APP_ID and API_KEY in config/index.tsx' : ''} />
|
return <AppUnavailable isUnknownReason={isUnknownReason} errMessage={!hasSetAppConfig ? 'Please set APP_ID and API_KEY in config/index.tsx' : ''} />
|
||||||
|
|
||||||
if (!APP_ID || !APP_INFO || !promptConfig)
|
if (!APP_ID || !APP_INFO || !promptConfig)
|
||||||
return <Loading type='app' />
|
return <Loading type='app' />
|
||||||
@ -639,7 +639,7 @@ const Main: FC = () => {
|
|||||||
siteInfo={APP_INFO}
|
siteInfo={APP_INFO}
|
||||||
promptConfig={promptConfig}
|
promptConfig={promptConfig}
|
||||||
onStartChat={handleStartChat}
|
onStartChat={handleStartChat}
|
||||||
canEidtInpus={canEditInpus}
|
canEditInputs={canEditInputs}
|
||||||
savedInputs={currInputs as Record<string, any>}
|
savedInputs={currInputs as Record<string, any>}
|
||||||
onInputsChange={setCurrInputs}
|
onInputsChange={setCurrInputs}
|
||||||
></ConfigSence>
|
></ConfigSence>
|
||||||
@ -652,7 +652,7 @@ const Main: FC = () => {
|
|||||||
chatList={chatList}
|
chatList={chatList}
|
||||||
onSend={handleSend}
|
onSend={handleSend}
|
||||||
onFeedback={handleFeedback}
|
onFeedback={handleFeedback}
|
||||||
isResponsing={isResponsing}
|
isResponding={isResponding}
|
||||||
checkCanSend={checkCanSend}
|
checkCanSend={checkCanSend}
|
||||||
visionConfig={visionConfig}
|
visionConfig={visionConfig}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@ -20,7 +20,7 @@ export type IWelcomeProps = {
|
|||||||
siteInfo: AppInfo
|
siteInfo: AppInfo
|
||||||
promptConfig: PromptConfig
|
promptConfig: PromptConfig
|
||||||
onStartChat: (inputs: Record<string, any>) => void
|
onStartChat: (inputs: Record<string, any>) => void
|
||||||
canEidtInpus: boolean
|
canEditInputs: boolean
|
||||||
savedInputs: Record<string, any>
|
savedInputs: Record<string, any>
|
||||||
onInputsChange: (inputs: Record<string, any>) => void
|
onInputsChange: (inputs: Record<string, any>) => void
|
||||||
}
|
}
|
||||||
@ -32,7 +32,7 @@ const Welcome: FC<IWelcomeProps> = ({
|
|||||||
siteInfo,
|
siteInfo,
|
||||||
promptConfig,
|
promptConfig,
|
||||||
onStartChat,
|
onStartChat,
|
||||||
canEidtInpus,
|
canEditInputs,
|
||||||
savedInputs,
|
savedInputs,
|
||||||
onInputsChange,
|
onInputsChange,
|
||||||
}) => {
|
}) => {
|
||||||
@ -131,8 +131,8 @@ const Welcome: FC<IWelcomeProps> = ({
|
|||||||
const canChat = () => {
|
const canChat = () => {
|
||||||
const inputLens = Object.values(inputs).length
|
const inputLens = Object.values(inputs).length
|
||||||
const promptVariablesLens = promptConfig.prompt_variables.length
|
const promptVariablesLens = promptConfig.prompt_variables.length
|
||||||
const emytyInput = inputLens < promptVariablesLens || Object.values(inputs).filter(v => v === '').length > 0
|
const emptyInput = inputLens < promptVariablesLens || Object.values(inputs).filter(v => v === '').length > 0
|
||||||
if (emytyInput) {
|
if (emptyInput) {
|
||||||
logError(t('app.errorMessage.valueOfVarRequired'))
|
logError(t('app.errorMessage.valueOfVarRequired'))
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -217,7 +217,7 @@ const Welcome: FC<IWelcomeProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const renderHasSetInputsPublic = () => {
|
const renderHasSetInputsPublic = () => {
|
||||||
if (!canEidtInpus) {
|
if (!canEditInputs) {
|
||||||
return (
|
return (
|
||||||
<TemplateVarPanel
|
<TemplateVarPanel
|
||||||
isFold={false}
|
isFold={false}
|
||||||
@ -260,7 +260,7 @@ const Welcome: FC<IWelcomeProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const renderHasSetInputsPrivate = () => {
|
const renderHasSetInputsPrivate = () => {
|
||||||
if (!canEidtInpus || !hasVar)
|
if (!canEditInputs || !hasVar)
|
||||||
return null
|
return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -284,7 +284,7 @@ const Welcome: FC<IWelcomeProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const renderHasSetInputs = () => {
|
const renderHasSetInputs = () => {
|
||||||
if ((!isPublicVersion && !canEidtInpus) || !hasVar)
|
if ((!isPublicVersion && !canEditInputs) || !hasVar)
|
||||||
return null
|
return null
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -3,13 +3,10 @@ import type { FC } from 'react'
|
|||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import cn from 'classnames'
|
import cn from 'classnames'
|
||||||
import BlockIcon from './block-icon'
|
import BlockIcon from './block-icon'
|
||||||
import CodeEditor from './code-editor'
|
|
||||||
import { CodeLanguage } from '@/types/app'
|
|
||||||
import AlertCircle from '@/app/components/base/icons/line/alert-circle'
|
import AlertCircle from '@/app/components/base/icons/line/alert-circle'
|
||||||
import AlertTriangle from '@/app/components/base/icons/line/alert-triangle'
|
import AlertTriangle from '@/app/components/base/icons/line/alert-triangle'
|
||||||
import Loading02 from '@/app/components/base/icons/line/loading-02'
|
import Loading02 from '@/app/components/base/icons/line/loading-02'
|
||||||
import CheckCircle from '@/app/components/base/icons/line/check-circle'
|
import CheckCircle from '@/app/components/base/icons/line/check-circle'
|
||||||
import ChevronRight from '@/app/components/base/icons/line/chevron-right'
|
|
||||||
import type { NodeTracing } from '@/types/app'
|
import type { NodeTracing } from '@/types/app'
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -52,12 +49,6 @@ const NodePanel: FC<Props> = ({ nodeInfo, hideInfo = false }) => {
|
|||||||
)}
|
)}
|
||||||
onClick={() => setCollapseState(!collapseState)}
|
onClick={() => setCollapseState(!collapseState)}
|
||||||
>
|
>
|
||||||
<ChevronRight
|
|
||||||
className={cn(
|
|
||||||
'shrink-0 w-3 h-3 mr-1 text-gray-400 transition-all group-hover:text-gray-500',
|
|
||||||
!collapseState && 'rotate-90',
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<BlockIcon size={hideInfo ? 'xs' : 'sm'} className={cn('shrink-0 mr-2', hideInfo && '!mr-1')} type={nodeInfo.node_type} toolIcon={nodeInfo.extras?.icon || nodeInfo.extras} />
|
<BlockIcon size={hideInfo ? 'xs' : 'sm'} className={cn('shrink-0 mr-2', hideInfo && '!mr-1')} type={nodeInfo.node_type} toolIcon={nodeInfo.extras?.icon || nodeInfo.extras} />
|
||||||
<div className={cn(
|
<div className={cn(
|
||||||
'grow text-gray-700 text-[13px] leading-[16px] font-semibold truncate',
|
'grow text-gray-700 text-[13px] leading-[16px] font-semibold truncate',
|
||||||
@ -82,48 +73,6 @@ const NodePanel: FC<Props> = ({ nodeInfo, hideInfo = false }) => {
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!collapseState && (
|
|
||||||
<div className='pb-2'>
|
|
||||||
<div className={cn('px-[10px] py-1', hideInfo && '!px-2 !py-0.5')}>
|
|
||||||
{nodeInfo.status === 'failed' && (
|
|
||||||
<div className='px-3 py-[10px] bg-[#fef3f2] rounded-lg border-[0.5px] border-[rbga(0,0,0,0.05)] text-xs leading-[18px] text-[#d92d20] shadow-xs'>{nodeInfo.error}</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
{nodeInfo.inputs && (
|
|
||||||
<div className={cn('px-[10px] py-1', hideInfo && '!px-2 !py-0.5')}>
|
|
||||||
<CodeEditor
|
|
||||||
readOnly
|
|
||||||
title={<div>INPUT</div>}
|
|
||||||
language={CodeLanguage.json}
|
|
||||||
value={nodeInfo.inputs}
|
|
||||||
isJSONStringifyBeauty
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{nodeInfo.process_data && (
|
|
||||||
<div className={cn('px-[10px] py-1', hideInfo && '!px-2 !py-0.5')}>
|
|
||||||
<CodeEditor
|
|
||||||
readOnly
|
|
||||||
title={<div>PROCESS DATA</div>}
|
|
||||||
language={CodeLanguage.json}
|
|
||||||
value={nodeInfo.process_data}
|
|
||||||
isJSONStringifyBeauty
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{nodeInfo.outputs && (
|
|
||||||
<div className={cn('px-[10px] py-1', hideInfo && '!px-2 !py-0.5')}>
|
|
||||||
<CodeEditor
|
|
||||||
readOnly
|
|
||||||
title={<div>OUTPUT</div>}
|
|
||||||
language={CodeLanguage.json}
|
|
||||||
value={nodeInfo.outputs}
|
|
||||||
isJSONStringifyBeauty
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -7,7 +7,7 @@ export const APP_INFO: AppInfo = {
|
|||||||
description: '',
|
description: '',
|
||||||
copyright: '',
|
copyright: '',
|
||||||
privacy_policy: '',
|
privacy_policy: '',
|
||||||
default_language: 'zh-Hans',
|
default_language: 'en',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const isShowPrompt = false
|
export const isShowPrompt = false
|
||||||
|
|||||||
@ -2,8 +2,10 @@
|
|||||||
import i18n from 'i18next'
|
import i18n from 'i18next'
|
||||||
import { initReactI18next } from 'react-i18next'
|
import { initReactI18next } from 'react-i18next'
|
||||||
import commonEn from './lang/common.en'
|
import commonEn from './lang/common.en'
|
||||||
|
import commonEs from './lang/common.es'
|
||||||
import commonZh from './lang/common.zh'
|
import commonZh from './lang/common.zh'
|
||||||
import appEn from './lang/app.en'
|
import appEn from './lang/app.en'
|
||||||
|
import appEs from './lang/app.es'
|
||||||
import appZh from './lang/app.zh'
|
import appZh from './lang/app.zh'
|
||||||
import toolsEn from './lang/tools.en'
|
import toolsEn from './lang/tools.en'
|
||||||
import toolsZh from './lang/tools.zh'
|
import toolsZh from './lang/tools.zh'
|
||||||
@ -18,6 +20,12 @@ const resources = {
|
|||||||
tools: toolsEn,
|
tools: toolsEn,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
'es': {
|
||||||
|
translation: {
|
||||||
|
common: commonEs,
|
||||||
|
app: appEs,
|
||||||
|
},
|
||||||
|
},
|
||||||
'zh-Hans': {
|
'zh-Hans': {
|
||||||
translation: {
|
translation: {
|
||||||
common: commonZh,
|
common: commonZh,
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
export const i18n = {
|
export const i18n = {
|
||||||
defaultLocale: 'en',
|
defaultLocale: 'en',
|
||||||
locales: ['en', 'zh-Hans'],
|
locales: ['en', 'es', 'zh-Hans'],
|
||||||
} as const
|
} as const
|
||||||
|
|
||||||
export type Locale = typeof i18n['locales'][number]
|
export type Locale = typeof i18n['locales'][number]
|
||||||
|
|||||||
33
i18n/lang/app.es.ts
Normal file
33
i18n/lang/app.es.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
const translation = {
|
||||||
|
common: {
|
||||||
|
welcome: 'Bienvenido a usar',
|
||||||
|
appUnavailable: 'App es inaccesible',
|
||||||
|
appUnkonwError: 'App es inaccesible',
|
||||||
|
},
|
||||||
|
chat: {
|
||||||
|
newChat: 'Nuevo chat',
|
||||||
|
newChatDefaultName: 'Nueva conversación',
|
||||||
|
openingStatementTitle: 'Frase de apertura',
|
||||||
|
powerBy: 'Desarrollado por',
|
||||||
|
prompt: 'Prompt',
|
||||||
|
privatePromptConfigTitle: 'Ajustes de conversación',
|
||||||
|
publicPromptConfigTitle: 'Prompt inicial',
|
||||||
|
configStatusDes: 'Antes de comenzar, puede modificar la configuración de la conversación',
|
||||||
|
configDisabled:
|
||||||
|
'La configuración de la sesión anterior se ha utilizado para esta sesión.',
|
||||||
|
startChat: 'Comenzar chat',
|
||||||
|
privacyPolicyLeft:
|
||||||
|
'Por favor lea la ',
|
||||||
|
privacyPolicyMiddle:
|
||||||
|
'política de privacidad',
|
||||||
|
privacyPolicyRight:
|
||||||
|
' proporcionada por el desarrollador de la aplicación.',
|
||||||
|
},
|
||||||
|
errorMessage: {
|
||||||
|
valueOfVarRequired: 'El valor de las variables no puede estar vacío',
|
||||||
|
waitForResponse:
|
||||||
|
'Por favor espere a que la respuesta al mensaje anterior se complete.',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default translation
|
||||||
33
i18n/lang/common.es.ts
Normal file
33
i18n/lang/common.es.ts
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
const translation = {
|
||||||
|
api: {
|
||||||
|
success: 'Éxito',
|
||||||
|
saved: 'Guardado',
|
||||||
|
create: 'Creado',
|
||||||
|
},
|
||||||
|
operation: {
|
||||||
|
confirm: 'Confirmar',
|
||||||
|
cancel: 'Cancelar',
|
||||||
|
clear: 'Limpiar',
|
||||||
|
save: 'Guardar',
|
||||||
|
edit: 'Editar',
|
||||||
|
refresh: 'Reiniciar',
|
||||||
|
search: 'Buscar',
|
||||||
|
send: 'Enviar',
|
||||||
|
lineBreak: 'Salto de línea',
|
||||||
|
like: 'Me gusta',
|
||||||
|
dislike: 'No me gusta',
|
||||||
|
ok: 'OK',
|
||||||
|
},
|
||||||
|
imageUploader: {
|
||||||
|
uploadFromComputer: 'Subir desde el ordenador',
|
||||||
|
uploadFromComputerReadError: 'La lectura de la imagen falló, por favor inténtelo de nuevo.',
|
||||||
|
uploadFromComputerUploadError: 'Error al subir la imagen, por favor inténtelo de nuevo.',
|
||||||
|
uploadFromComputerLimit: 'Las imágenes subidas no pueden superar los {{size}} MB',
|
||||||
|
pasteImageLink: 'Pegar enlace de imagen',
|
||||||
|
pasteImageLinkInputPlaceholder: 'Pegar enlace de imagen aquí',
|
||||||
|
pasteImageLinkInvalid: 'Enlace de imagen no válido',
|
||||||
|
imageUpload: 'Subir imagen',
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export default translation
|
||||||
Reference in New Issue
Block a user