'use client' import type { FC } from 'react' import React, { useEffect, useState } from 'react' import { useBoolean, useGetState } from 'ahooks' import { t } from 'i18next' import cn from 'classnames' import TextGenerationRes from '@/app/components/app/text-generate/item' import NoData from '@/app/components/share/text-generation/no-data' import Toast from '@/app/components/base/toast' import { sendCompletionMessage, updateFeedback } from '@/service/share' import type { Feedbacktype } from '@/app/components/app/chat' import Loading from '@/app/components/base/loading' import type { PromptConfig } from '@/models/debug' import type { InstalledApp } from '@/models/explore' export type IResultProps = { isCallBatchAPI: boolean isPC: boolean isMobile: boolean isInstalledApp: boolean installedAppInfo?: InstalledApp promptConfig: PromptConfig | null moreLikeThisEnabled: boolean inputs: Record query: string controlSend?: number controlStopResponding?: number onShowRes: () => void handleSaveMessage: (messageId: string) => void taskId?: number onCompleted: (completionRes: string, taskId?: number, success?: boolean) => void } const Result: FC = ({ isCallBatchAPI, isPC, isMobile, isInstalledApp, installedAppInfo, promptConfig, moreLikeThisEnabled, inputs, query, controlSend, controlStopResponding, onShowRes, handleSaveMessage, taskId, onCompleted, }) => { const [isResponsing, { setTrue: setResponsingTrue, setFalse: setResponsingFalse }] = useBoolean(false) useEffect(() => { if (controlStopResponding) setResponsingFalse() }, [controlStopResponding]) const [completionRes, setCompletionRes, getCompletionRes] = useGetState('') const { notify } = Toast const isNoData = !completionRes const [messageId, setMessageId] = useState(null) const [feedback, setFeedback] = useState({ rating: null, }) const handleFeedback = async (feedback: Feedbacktype) => { await updateFeedback({ url: `/messages/${messageId}/feedbacks`, body: { rating: feedback.rating } }, isInstalledApp, installedAppInfo?.id) setFeedback(feedback) } const logError = (message: string) => { notify({ type: 'error', message }) } const checkCanSend = () => { // batch will check outer if (isCallBatchAPI) return true const prompt_variables = promptConfig?.prompt_variables if (!prompt_variables || prompt_variables?.length === 0) return true let hasEmptyInput = '' const requiredVars = prompt_variables?.filter(({ key, name, required }) => { const res = (!key || !key.trim()) || (!name || !name.trim()) || (required || required === undefined || required === null) return res }) || [] // compatible with old version requiredVars.forEach(({ key, name }) => { if (hasEmptyInput) return if (!inputs[key]) hasEmptyInput = name }) if (hasEmptyInput) { logError(t('appDebug.errorMessage.valueOfVarRequired', { key: hasEmptyInput })) return false } return !hasEmptyInput } const handleSend = async () => { if (isResponsing) { notify({ type: 'info', message: t('appDebug.errorMessage.waitForResponse') }) return false } if (!checkCanSend()) return if (!query) { logError(t('appDebug.errorMessage.queryRequired')) return false } const data = { inputs, query, } setMessageId(null) setFeedback({ rating: null, }) setCompletionRes('') const res: string[] = [] let tempMessageId = '' if (!isPC) onShowRes() setResponsingTrue() sendCompletionMessage(data, { onData: (data: string, _isFirstMessage: boolean, { messageId }: any) => { tempMessageId = messageId res.push(data) setCompletionRes(res.join('')) }, onCompleted: () => { setResponsingFalse() setMessageId(tempMessageId) onCompleted(getCompletionRes(), taskId, true) }, onError() { setResponsingFalse() onCompleted(getCompletionRes(), taskId, false) }, }, isInstalledApp, installedAppInfo?.id) } const [controlClearMoreLikeThis, setControlClearMoreLikeThis] = useState(0) useEffect(() => { if (controlSend) { handleSend() setControlClearMoreLikeThis(Date.now()) } }, [controlSend]) const renderTextGenerationRes = () => ( ) return (
{!isCallBatchAPI && ( (isResponsing && !completionRes) ? (
) : ( <> {isNoData ? : renderTextGenerationRes() } ) )} {isCallBatchAPI && (
{renderTextGenerationRes()}
)}
) } export default React.memo(Result)