diff --git a/packages/global/core/chat/utils.ts b/packages/global/core/chat/utils.ts index 3c252861c..e8900081c 100644 --- a/packages/global/core/chat/utils.ts +++ b/packages/global/core/chat/utils.ts @@ -78,11 +78,15 @@ export const getHistoryPreview = ( }; export const filterPublicNodeResponseData = ({ - flowResponses = [] + flowResponses = [], + responseDetail = false }: { flowResponses?: ChatHistoryItemResType[]; + responseDetail?: boolean; }) => { - const filedList = ['quoteList', 'moduleType', 'pluginOutput', 'runningTime']; + const filedList = responseDetail + ? ['quoteList', 'moduleType', 'pluginOutput', 'runningTime'] + : ['moduleType', 'pluginOutput', 'runningTime']; const filterModuleTypeList: any[] = [ FlowNodeTypeEnum.pluginModule, FlowNodeTypeEnum.datasetSearchNode, diff --git a/packages/service/core/workflow/dispatch/dataset/search.ts b/packages/service/core/workflow/dispatch/dataset/search.ts index dce339587..2691a487b 100644 --- a/packages/service/core/workflow/dispatch/dataset/search.ts +++ b/packages/service/core/workflow/dispatch/dataset/search.ts @@ -65,6 +65,18 @@ export async function dispatchDatasetSearch( } if (!userChatInput) { + return { + quoteQA: [], + [DispatchNodeResponseKeyEnum.nodeResponse]: { + totalPoints: 0, + query: '', + limit, + searchMode + }, + nodeDispatchUsages: [], + [DispatchNodeResponseKeyEnum.toolResponses]: [] + }; + return Promise.reject(i18nT('common:core.chat.error.User input empty')); } diff --git a/packages/web/hooks/useWidthVariable.ts b/packages/web/hooks/useWidthVariable.ts index 77a185f88..7cd37ce30 100644 --- a/packages/web/hooks/useWidthVariable.ts +++ b/packages/web/hooks/useWidthVariable.ts @@ -11,11 +11,14 @@ export const useWidthVariable = ({ }) => { const value = useMemo(() => { // 根据 width 计算,找到第一个大于 width 的值 - const index = widthList.findLastIndex((item) => width > item); + const reversedWidthList = [...widthList].reverse(); + const reversedList = [...list].reverse(); + const index = reversedWidthList.findIndex((item) => width > item); + if (index === -1) { - return list[0]; + return reversedList[0]; } - return list[index]; + return reversedList[index]; }, [list, width, widthList]); return value; diff --git a/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ResponseTags.tsx b/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ResponseTags.tsx index f8596d59f..6c0009bc1 100644 --- a/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ResponseTags.tsx +++ b/projects/app/src/components/core/chat/ChatContainer/ChatBox/components/ResponseTags.tsx @@ -30,6 +30,7 @@ const ResponseTags = ({ const { t } = useTranslation(); const quoteListRef = React.useRef(null); const dataId = historyItem.dataId; + const { totalQuoteList: quoteList = [], llmModuleAccount = 0, diff --git a/projects/app/src/global/core/chat/utils.ts b/projects/app/src/global/core/chat/utils.ts index 2fd1e6c86..30719a962 100644 --- a/projects/app/src/global/core/chat/utils.ts +++ b/projects/app/src/global/core/chat/utils.ts @@ -6,11 +6,15 @@ import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant'; const isLLMNode = (item: ChatHistoryItemResType) => item.moduleType === FlowNodeTypeEnum.chatNode || item.moduleType === FlowNodeTypeEnum.tools; -export function transformPreviewHistories(histories: ChatItemType[]): ChatItemType[] { +export function transformPreviewHistories( + histories: ChatItemType[], + responseDetail: boolean +): ChatItemType[] { return histories.map((item) => { return { ...addStatisticalDataToHistoryItem(item), - responseData: undefined + responseData: undefined, + ...(responseDetail ? {} : { totalQuoteList: undefined }) }; }); } @@ -18,6 +22,7 @@ export function transformPreviewHistories(histories: ChatItemType[]): ChatItemTy export function addStatisticalDataToHistoryItem(historyItem: ChatItemType) { if (historyItem.obj !== ChatRoleEnum.AI) return historyItem; if (historyItem.totalQuoteList !== undefined) return historyItem; + if (!historyItem.responseData) return historyItem; // Flat children const flatResData: ChatHistoryItemResType[] = diff --git a/projects/app/src/pages/api/core/chat/getPaginationRecords.ts b/projects/app/src/pages/api/core/chat/getPaginationRecords.ts index e32b755e4..f7b3cb631 100644 --- a/projects/app/src/pages/api/core/chat/getPaginationRecords.ts +++ b/projects/app/src/pages/api/core/chat/getPaginationRecords.ts @@ -82,11 +82,16 @@ async function handler( limit: pageSize }); + const responseDetail = !shareChat || shareChat.responseDetail; + // Remove important information if (shareChat && app.type !== AppTypeEnum.plugin) { histories.forEach((item) => { if (item.obj === ChatRoleEnum.AI) { - item.responseData = filterPublicNodeResponseData({ flowResponses: item.responseData }); + item.responseData = filterPublicNodeResponseData({ + flowResponses: item.responseData, + responseDetail + }); if (shareChat.showNodeStatus === false) { item.value = item.value.filter((v) => v.type !== ChatItemValueTypeEnum.tool); @@ -96,7 +101,7 @@ async function handler( } return { - list: isPlugin ? histories : transformPreviewHistories(histories), + list: isPlugin ? histories : transformPreviewHistories(histories, responseDetail), total }; } diff --git a/projects/app/src/pages/api/core/chat/getResData.ts b/projects/app/src/pages/api/core/chat/getResData.ts index c306f707c..4f742563a 100644 --- a/projects/app/src/pages/api/core/chat/getResData.ts +++ b/projects/app/src/pages/api/core/chat/getResData.ts @@ -11,6 +11,7 @@ import { ChatHistoryItemResType } from '@fastgpt/global/core/chat/type'; import { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat'; import { authApp } from '@fastgpt/service/support/permission/app/auth'; import { filterPublicNodeResponseData } from '@fastgpt/global/core/chat/utils'; +import { MongoOutLink } from '@fastgpt/service/support/outLink/schema'; export type getResDataQuery = OutLinkChatAuthProps & { chatId?: string; @@ -26,44 +27,57 @@ async function handler( req: ApiRequestProps, res: ApiResponseType ): Promise { - const { appId, chatId, dataId } = req.query; + const { appId, chatId, dataId, shareId } = req.query; if (!appId || !chatId || !dataId) { return {}; } // 1. Un login api: share chat, team chat // 2. Login api: account chat, chat log - try { - await authChatCrud({ - req, - authToken: true, - authApiKey: true, - ...req.query, - per: ReadPermissionVal - }); - } catch (error) { - await authApp({ - req, - authToken: true, - authApiKey: true, - appId, - per: ManagePermissionVal - }); + const authData = await (() => { + try { + return authChatCrud({ + req, + authToken: true, + authApiKey: true, + ...req.query, + per: ReadPermissionVal + }); + } catch (error) { + return authApp({ + req, + authToken: true, + authApiKey: true, + appId, + per: ManagePermissionVal + }); + } + })(); + + const [chatData] = await Promise.all([ + MongoChatItem.findOne( + { + appId, + chatId, + dataId + }, + 'obj responseData' + ).lean(), + shareId ? MongoOutLink.findOne({ shareId }).lean() : Promise.resolve(null) + ]); + + if (chatData?.obj !== ChatRoleEnum.AI) { + return {}; } - const chatData = await MongoChatItem.findOne( - { - appId, - chatId, - dataId - }, - 'obj responseData' - ).lean(); - - if (chatData?.obj === ChatRoleEnum.AI) { - const data = chatData.responseData || {}; - return req.query.shareId ? filterPublicNodeResponseData(data) : data; - } else return {}; + const flowResponses = chatData.responseData ?? {}; + return req.query.shareId + ? filterPublicNodeResponseData({ + // @ts-ignore + responseDetail: authData.responseDetail, + flowResponses: chatData.responseData + }) + : flowResponses; } export default NextAPI(handler); diff --git a/projects/app/src/pages/api/v1/chat/completions.ts b/projects/app/src/pages/api/v1/chat/completions.ts index 8d017ff27..cc2ad7fb6 100644 --- a/projects/app/src/pages/api/v1/chat/completions.ts +++ b/projects/app/src/pages/api/v1/chat/completions.ts @@ -363,7 +363,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { /* select fe response field */ const feResponseData = canWrite ? flowResponses - : filterPublicNodeResponseData({ flowResponses }); + : filterPublicNodeResponseData({ flowResponses, responseDetail }); if (stream) { workflowResponseWrite({ @@ -380,12 +380,10 @@ async function handler(req: NextApiRequest, res: NextApiResponse) { }); if (detail) { - if (responseDetail || isPlugin) { - workflowResponseWrite({ - event: SseResponseEventEnum.flowResponses, - data: feResponseData - }); - } + workflowResponseWrite({ + event: SseResponseEventEnum.flowResponses, + data: feResponseData + }); } res.end(); diff --git a/projects/app/src/service/support/permission/auth/chat.ts b/projects/app/src/service/support/permission/auth/chat.ts index 1699c5af4..06f5dd0a4 100644 --- a/projects/app/src/service/support/permission/auth/chat.ts +++ b/projects/app/src/service/support/permission/auth/chat.ts @@ -42,18 +42,19 @@ export async function authChatCrud({ chat?: ChatSchema; isOutLink: boolean; uid?: string; + responseDetail: boolean; }> { const isOutLink = Boolean((shareId || spaceTeamId) && outLinkUid); - if (!chatId) return { isOutLink, uid: outLinkUid }; + if (!chatId) return { isOutLink, uid: outLinkUid, responseDetail: true }; const chat = await MongoChat.findOne({ appId, chatId }).lean(); - const { uid } = await (async () => { + const { uid, responseDetail } = await (async () => { // outLink Auth if (shareId && outLinkUid) { - const { uid } = await authOutLink({ shareId, outLinkUid }); + const { uid, shareChat } = await authOutLink({ shareId, outLinkUid }); if (!chat || (chat.shareId === shareId && chat.outLinkUid === uid)) { - return { uid }; + return { uid, responseDetail: shareChat.responseDetail }; } return Promise.reject(ChatErrEnum.unAuthChat); } @@ -62,12 +63,12 @@ export async function authChatCrud({ const { uid } = await authTeamSpaceToken({ teamId: spaceTeamId, teamToken }); addLog.debug('Auth team token', { uid, spaceTeamId, teamToken, chatUid: chat?.outLinkUid }); if (!chat || (String(chat.teamId) === String(spaceTeamId) && chat.outLinkUid === uid)) { - return { uid }; + return { uid, responseDetail: true }; } return Promise.reject(ChatErrEnum.unAuthChat); } - if (!chat) return { id: outLinkUid }; + if (!chat) return { id: outLinkUid, responseDetail: true }; // auth req const { teamId, tmbId, permission } = await authApp({ @@ -80,18 +81,19 @@ export async function authChatCrud({ if (String(teamId) !== String(chat.teamId)) return Promise.reject(ChatErrEnum.unAuthChat); - if (permission.hasManagePer) return { uid: outLinkUid }; - if (String(tmbId) === String(chat.tmbId)) return { uid: outLinkUid }; + if (permission.hasManagePer) return { uid: outLinkUid, responseDetail: true }; + if (String(tmbId) === String(chat.tmbId)) return { uid: outLinkUid, responseDetail: true }; return Promise.reject(ChatErrEnum.unAuthChat); })(); - if (!chat) return { isOutLink, uid }; + if (!chat) return { isOutLink, uid, responseDetail }; return { chat, isOutLink, - uid + uid, + responseDetail }; }