V4.7-alpha (#985)

Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
This commit is contained in:
Archer
2024-03-13 10:50:02 +08:00
committed by GitHub
parent 5bca15f12f
commit 9501c3f3a1
170 changed files with 5786 additions and 2342 deletions

View File

@@ -1,20 +1,22 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { connectToDatabase } from '@/service/mongo';
import { sseErrRes } from '@fastgpt/service/common/response';
import { sseResponseEventEnum } from '@fastgpt/service/common/response/constant';
import { SseResponseEventEnum } from '@fastgpt/global/core/module/runtime/constants';
import { responseWrite } from '@fastgpt/service/common/response';
import type { ModuleItemType } from '@fastgpt/global/core/module/type.d';
import { pushChatUsage } from '@/service/support/wallet/usage/push';
import { UsageSourceEnum } from '@fastgpt/global/support/wallet/usage/constants';
import type { ChatItemType } from '@fastgpt/global/core/chat/type';
import type { ChatItemType, ChatItemValueItemType } from '@fastgpt/global/core/chat/type';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { dispatchModules } from '@/service/moduleDispatch';
import { dispatchWorkFlow } from '@/service/moduleDispatch';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { getUserChatInfoAndAuthTeamPoints } from '@/service/support/permission/auth/team';
import { setEntryEntries } from '@/service/moduleDispatch/utils';
import { chatValue2RuntimePrompt } from '@fastgpt/global/core/chat/adapt';
export type Props = {
history: ChatItemType[];
prompt: string;
prompt: ChatItemValueItemType[];
modules: ModuleItemType[];
variables: Record<string, any>;
appId: string;
@@ -33,7 +35,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
let { modules = [], history = [], prompt, variables = {}, appName, appId } = req.body as Props;
try {
await connectToDatabase();
if (!history || !modules || !prompt) {
if (!history || !modules || !prompt || prompt.length === 0) {
throw new Error('Prams Error');
}
if (!Array.isArray(modules)) {
@@ -52,19 +54,22 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
// auth balance
const { user } = await getUserChatInfoAndAuthTeamPoints(tmbId);
const { text, files } = chatValue2RuntimePrompt(prompt);
/* start process */
const { responseData, moduleDispatchBills } = await dispatchModules({
const { flowResponses, flowUsages } = await dispatchWorkFlow({
res,
mode: 'test',
teamId,
tmbId,
user,
appId,
modules,
modules: setEntryEntries(modules),
variables,
inputFiles: files,
histories: history,
startParams: {
userChatInput: prompt
userChatInput: text
},
stream: true,
detail: true
@@ -72,13 +77,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
responseWrite({
res,
event: sseResponseEventEnum.answer,
event: SseResponseEventEnum.answer,
data: '[DONE]'
});
responseWrite({
res,
event: sseResponseEventEnum.appStreamResponse,
data: JSON.stringify(responseData)
event: SseResponseEventEnum.flowResponses,
data: JSON.stringify(flowResponses)
});
res.end();
@@ -88,7 +93,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
teamId,
tmbId,
source: UsageSourceEnum.fastgpt,
moduleDispatchBills
flowUsages
});
} catch (err: any) {
res.status(500);

View File

@@ -4,11 +4,11 @@ import { connectToDatabase } from '@/service/mongo';
import { authApp } from '@fastgpt/service/support/permission/auth/app';
import { getGuideModule } from '@fastgpt/global/core/module/utils';
import { getChatModelNameListByModules } from '@/service/core/app/module';
import { ModuleOutputKeyEnum } from '@fastgpt/global/core/module/constants';
import type { InitChatProps, InitChatResponse } from '@/global/core/chat/api.d';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import { getChatItems } from '@fastgpt/service/core/chat/controller';
import { ChatErrEnum } from '@fastgpt/global/common/error/code/chat';
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/module/runtime/constants';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
@@ -45,7 +45,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
chatId,
limit: 30,
field: `dataId obj value adminFeedback userBadFeedback userGoodFeedback ${
ModuleOutputKeyEnum.responseData
DispatchNodeResponseKeyEnum.nodeResponse
} ${loadCustomFeedbacks ? 'customFeedbacks' : ''}`
});

View File

@@ -4,15 +4,16 @@ import { connectToDatabase } from '@/service/mongo';
import type { InitChatResponse, InitOutLinkChatProps } from '@/global/core/chat/api.d';
import { getGuideModule } from '@fastgpt/global/core/module/utils';
import { getChatModelNameListByModules } from '@/service/core/app/module';
import { ModuleOutputKeyEnum } from '@fastgpt/global/core/module/constants';
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/module/runtime/constants';
import { getChatItems } from '@fastgpt/service/core/chat/controller';
import { MongoTeamMember } from '@fastgpt/service/support/user/team/teamMemberSchema';
import { authOutLink } from '@/service/support/permission/auth/outLink';
import { MongoApp } from '@fastgpt/service/core/app/schema';
import { selectSimpleChatResponse } from '@/utils/service/core/chat';
import { filterPublicNodeResponseData } from '@fastgpt/global/core/chat/utils';
import { AppErrEnum } from '@fastgpt/global/common/error/code/app';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import { ChatErrEnum } from '@fastgpt/global/common/error/code/chat';
import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
@@ -44,13 +45,15 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
chatId,
limit: 30,
field: `dataId obj value userGoodFeedback userBadFeedback ${
shareChat.responseDetail ? `adminFeedback ${ModuleOutputKeyEnum.responseData}` : ''
shareChat.responseDetail ? `adminFeedback ${DispatchNodeResponseKeyEnum.nodeResponse}` : ''
} `
});
// pick share response field
history.forEach((item) => {
item.responseData = selectSimpleChatResponse({ responseData: item.responseData });
if (item.obj === ChatRoleEnum.AI) {
item.responseData = filterPublicNodeResponseData({ flowResponses: item.responseData });
}
});
jsonRes<InitChatResponse>(res, {

View File

@@ -3,7 +3,7 @@ import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { getGuideModule } from '@fastgpt/global/core/module/utils';
import { getChatModelNameListByModules } from '@/service/core/app/module';
import { ModuleOutputKeyEnum } from '@fastgpt/global/core/module/constants';
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/module/runtime/constants';
import type { InitChatResponse, InitTeamChatProps } from '@/global/core/chat/api.d';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import { MongoApp } from '@fastgpt/service/core/app/schema';
@@ -12,7 +12,8 @@ import { AppErrEnum } from '@fastgpt/global/common/error/code/app';
import { authTeamSpaceToken } from '@/service/support/permission/auth/team';
import { MongoTeam } from '@fastgpt/service/support/user/team/teamSchema';
import { ChatErrEnum } from '@fastgpt/global/common/error/code/chat';
import { selectSimpleChatResponse } from '@/utils/service/core/chat';
import { filterPublicNodeResponseData } from '@fastgpt/global/core/chat/utils';
import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
@@ -49,12 +50,14 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
appId,
chatId,
limit: 30,
field: `dataId obj value userGoodFeedback userBadFeedback adminFeedback ${ModuleOutputKeyEnum.responseData}`
field: `dataId obj value userGoodFeedback userBadFeedback adminFeedback ${DispatchNodeResponseKeyEnum.nodeResponse}`
});
// pick share response field
history.forEach((item) => {
item.responseData = selectSimpleChatResponse({ responseData: item.responseData });
if (item.obj === ChatRoleEnum.AI) {
item.responseData = filterPublicNodeResponseData({ flowResponses: item.responseData });
}
});
jsonRes<InitChatResponse>(res, {

View File

@@ -9,6 +9,7 @@ import type { InitChatProps, InitChatResponse } from '@/global/core/chat/api.d';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import { getChatItems } from '@fastgpt/service/core/chat/controller';
import { ChatErrEnum } from '@fastgpt/global/common/error/code/chat';
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/module/runtime/constants';
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
@@ -45,7 +46,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
chatId,
limit: 30,
field: `dataId obj value adminFeedback userBadFeedback userGoodFeedback ${
ModuleOutputKeyEnum.responseData
DispatchNodeResponseKeyEnum.nodeResponse
} ${loadCustomFeedbacks ? 'customFeedbacks' : ''}`
});

View File

@@ -5,11 +5,12 @@ import { sseErrRes, jsonRes } from '@fastgpt/service/common/response';
import { addLog } from '@fastgpt/service/common/system/log';
import { withNextCors } from '@fastgpt/service/common/middle/cors';
import { ChatRoleEnum, ChatSourceEnum } from '@fastgpt/global/core/chat/constants';
import { sseResponseEventEnum } from '@fastgpt/service/common/response/constant';
import { dispatchModules } from '@/service/moduleDispatch';
import { SseResponseEventEnum } from '@fastgpt/global/core/module/runtime/constants';
import { dispatchWorkFlow } from '@/service/moduleDispatch';
import type { ChatCompletionCreateParams } from '@fastgpt/global/core/ai/type.d';
import type { ChatMessageItemType } from '@fastgpt/global/core/ai/type.d';
import { gptMessage2ChatType, textAdaptGptResponse } from '@/utils/adapt';
import type { ChatCompletionMessageParam } from '@fastgpt/global/core/ai/type.d';
import { textAdaptGptResponse } from '@fastgpt/global/core/module/runtime/utils';
import { GPTMessages2Chats, chatValue2RuntimePrompt } from '@fastgpt/global/core/chat/adapt';
import { getChatItems } from '@fastgpt/service/core/chat/controller';
import { saveChat } from '@/service/utils/chat/saveChat';
import { responseWrite } from '@fastgpt/service/common/response';
@@ -19,7 +20,7 @@ import { pushResult2Remote, addOutLinkUsage } from '@fastgpt/service/support/out
import requestIp from 'request-ip';
import { getUsageSourceByAuthType } from '@fastgpt/global/support/wallet/usage/tools';
import { authTeamSpaceToken } from '@/service/support/permission/auth/team';
import { selectSimpleChatResponse } from '@/utils/service/core/chat';
import { filterPublicNodeResponseData } from '@fastgpt/global/core/chat/utils';
import { updateApiKeyUsage } from '@fastgpt/service/support/openapi/tools';
import { connectToDatabase } from '@/service/mongo';
import { getUserChatInfoAndAuthTeamPoints } from '@/service/support/permission/auth/team';
@@ -31,6 +32,9 @@ import { AuthOutLinkChatProps } from '@fastgpt/global/support/outLink/api';
import { MongoChat } from '@fastgpt/service/core/chat/chatSchema';
import { ChatErrEnum } from '@fastgpt/global/common/error/code/chat';
import { OutLinkChatAuthProps } from '@fastgpt/global/support/permission/chat';
import { setEntryEntries } from '@/service/moduleDispatch/utils';
import { UserChatItemType } from '@fastgpt/global/core/chat/type';
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/module/runtime/constants';
type FastGptWebChatProps = {
chatId?: string; // undefined: nonuse history, '': new chat, 'xxxxx': use history
@@ -40,7 +44,7 @@ type FastGptWebChatProps = {
export type Props = ChatCompletionCreateParams &
FastGptWebChatProps &
OutLinkChatAuthProps & {
messages: ChatMessageItemType[];
messages: ChatCompletionMessageParam[];
stream?: boolean;
detail?: boolean;
variables: Record<string, any>;
@@ -102,17 +106,19 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
let startTime = Date.now();
const chatMessages = gptMessage2ChatType(messages);
const chatMessages = GPTMessages2Chats(messages);
if (chatMessages[chatMessages.length - 1].obj !== ChatRoleEnum.Human) {
chatMessages.pop();
}
// user question
const question = chatMessages.pop();
const question = chatMessages.pop() as UserChatItemType;
if (!question) {
throw new Error('Question is empty');
}
const { text, files } = chatValue2RuntimePrompt(question.value);
/*
1. auth app permission
2. auth balance
@@ -128,7 +134,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
outLinkUid,
chatId,
ip: originIp,
question: question.value
question: text
});
}
// team space chat
@@ -161,7 +167,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
const responseChatItemId: string | undefined = messages[messages.length - 1].dataId;
/* start flow controller */
const { responseData, moduleDispatchBills, answerText } = await dispatchModules({
const { flowResponses, flowUsages, assistantResponses } = await dispatchWorkFlow({
res,
mode: 'chat',
user,
@@ -170,11 +176,12 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
appId: String(app._id),
chatId,
responseChatItemId,
modules: app.modules,
modules: setEntryEntries(app.modules),
variables,
inputFiles: files,
histories: concatHistories,
startParams: {
userChatInput: question.value
userChatInput: text
},
stream,
detail
@@ -209,8 +216,8 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
{
dataId: responseChatItemId,
obj: ChatRoleEnum.AI,
value: answerText,
responseData
value: assistantResponses,
[DispatchNodeResponseKeyEnum.nodeResponse]: flowResponses
}
],
metadata: {
@@ -222,12 +229,14 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
addLog.info(`completions running time: ${(Date.now() - startTime) / 1000}s`);
/* select fe response field */
const feResponseData = canWrite ? responseData : selectSimpleChatResponse({ responseData });
const feResponseData = canWrite
? flowResponses
: filterPublicNodeResponseData({ flowResponses });
if (stream) {
responseWrite({
res,
event: detail ? sseResponseEventEnum.answer : undefined,
event: detail ? SseResponseEventEnum.answer : undefined,
data: textAdaptGptResponse({
text: null,
finish_reason: 'stop'
@@ -235,20 +244,26 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
});
responseWrite({
res,
event: detail ? sseResponseEventEnum.answer : undefined,
event: detail ? SseResponseEventEnum.answer : undefined,
data: '[DONE]'
});
if (responseDetail && detail) {
responseWrite({
res,
event: sseResponseEventEnum.appStreamResponse,
event: SseResponseEventEnum.flowResponses,
data: JSON.stringify(feResponseData)
});
}
res.end();
} else {
const responseContent = (() => {
if (assistantResponses.length === 0) return '';
if (assistantResponses.length === 1 && assistantResponses[0].text?.content)
return assistantResponses[0].text?.content;
return assistantResponses;
})();
res.json({
...(detail ? { responseData: feResponseData } : {}),
id: chatId || '',
@@ -256,7 +271,7 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
usage: { prompt_tokens: 1, completion_tokens: 1, total_tokens: 1 },
choices: [
{
message: { role: 'assistant', content: answerText },
message: { role: 'assistant', content: responseContent },
finish_reason: 'stop',
index: 0
}
@@ -271,11 +286,11 @@ export default withNextCors(async function handler(req: NextApiRequest, res: Nex
teamId,
tmbId: tmbId,
source: getUsageSourceByAuthType({ shareId, authType }),
moduleDispatchBills
flowUsages
});
if (shareId) {
pushResult2Remote({ outLinkUid, shareId, appName: app.name, responseData });
pushResult2Remote({ outLinkUid, shareId, appName: app.name, flowResponses });
addOutLinkUsage({
shareId,
totalPoints

View File

@@ -12,7 +12,7 @@ import dynamic from 'next/dynamic';
import MyIcon from '@fastgpt/web/components/common/Icon';
import MyTooltip from '@/components/MyTooltip';
import ChatTest, { type ChatTestComponentRef } from '@/components/core/module/Flow/ChatTest';
import { getFlowStore } from '@/components/core/module/Flow/FlowProvider';
import { useFlowProviderStore } from '@/components/core/module/Flow/FlowProvider';
import { flowNode2Modules, filterExportModules } from '@/components/core/module/utils';
import { useAppStore } from '@/web/core/app/store/useAppStore';
import { useToast } from '@fastgpt/web/hooks/useToast';
@@ -42,17 +42,18 @@ const RenderHeaderContainer = React.memo(function RenderHeaderContainer({
});
const { isOpen: isOpenImport, onOpen: onOpenImport, onClose: onCloseImport } = useDisclosure();
const { updateAppDetail } = useAppStore();
const { nodes, edges, splitToolInputs } = useFlowProviderStore();
const flow2ModulesAndCheck = useCallback(async () => {
const { nodes, edges } = await getFlowStore();
const modules = flowNode2Modules({ nodes, edges });
// check required connect
for (let i = 0; i < modules.length; i++) {
const item = modules[i];
const { isTool } = splitToolInputs(item.inputs, item.moduleId);
const unconnected = item.inputs.find((input) => {
if (!input.required || input.connected) {
if (!input.required || input.connected || (isTool && input.toolDescription)) {
return false;
}
if (input.value === undefined || input.value === '' || input.value?.length === 0) {
@@ -72,7 +73,7 @@ const RenderHeaderContainer = React.memo(function RenderHeaderContainer({
}
}
return modules;
}, [t, toast]);
}, [edges, nodes, splitToolInputs, t, toast]);
const { mutate: onclickSave, isLoading } = useRequest({
mutationFn: async (modules: ModuleItemType[]) => {
@@ -97,6 +98,7 @@ const RenderHeaderContainer = React.memo(function RenderHeaderContainer({
borderBottom={theme.borders.base}
alignItems={'center'}
userSelect={'none'}
bg={'myGray.25'}
>
<IconButton
size={'smSquare'}

View File

@@ -4,7 +4,7 @@ import Header from './Header';
import Flow from '@/components/core/module/Flow';
import FlowProvider, { useFlowProviderStore } from '@/components/core/module/Flow/FlowProvider';
import type { FlowModuleTemplateType } from '@fastgpt/global/core/module/type.d';
import { appSystemModuleTemplates } from '@/web/core/modules/template/system';
import { appSystemModuleTemplates } from '@fastgpt/global/core/module/template/constants';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
import { usePluginStore } from '@/web/core/plugin/store/plugin';
import { useQuery } from '@tanstack/react-query';

View File

@@ -21,7 +21,8 @@ import { ChatSourceMap } from '@fastgpt/global/core/chat/constants';
import { HUMAN_ICON } from '@fastgpt/global/common/system/constants';
import { AppLogsListItemType } from '@/types/app';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import ChatBox, { type ComponentRef } from '@/components/ChatBox';
import ChatBox from '@/components/ChatBox';
import type { ComponentRef } from '@/components/ChatBox/type.d';
import { useQuery } from '@tanstack/react-query';
import { getInitChatInfo } from '@/web/core/chat/api';
import Tag from '@/components/Tag';
@@ -30,6 +31,7 @@ import { addDays } from 'date-fns';
import MyBox from '@/components/common/MyBox';
import { usePagination } from '@fastgpt/web/hooks/usePagination';
import DateRangePicker, { DateRangeType } from '@fastgpt/web/components/common/DateRangePicker';
import { formatChatValue2InputType } from '@/components/ChatBox/utils';
const Logs = ({ appId }: { appId: string }) => {
const { t } = useTranslation();
@@ -248,7 +250,8 @@ const DetailLogsModal = ({
const history = useMemo(() => (chat?.history ? chat.history : []), [chat]);
const title = useMemo(() => {
return history[history.length - 2]?.value?.slice(0, 8);
const { text } = formatChatValue2InputType(history[history.length - 2]?.value);
return text?.slice(0, 8);
}, [history]);
return (

View File

@@ -128,9 +128,7 @@ const Share = ({ appId }: { appId: string }) => {
<Th>{item?.limit?.hookUrl ? '✔' : '✖'}</Th>
</>
)}
<Td>
{item.lastTime ? t(formatTimeToChatTime(item.lastTime)) : t('common.Un used')}
</Td>
<Td>{item.lastTime ? formatTimeToChatTime(item.lastTime) : t('common.Un used')}</Td>
<Td display={'flex'} alignItems={'center'}>
<MyMenu
Button={

View File

@@ -3,7 +3,8 @@ import { useUserStore } from '@/web/support/user/useUserStore';
import { Box, Flex, IconButton } from '@chakra-ui/react';
import { useTranslation } from 'next-i18next';
import React, { useCallback, useEffect, useRef, useState } from 'react';
import ChatBox, { type ComponentRef, type StartChatFnProps } from '@/components/ChatBox';
import ChatBox from '@/components/ChatBox';
import type { ComponentRef, StartChatFnProps } from '@/components/ChatBox/type.d';
import { ModuleItemType } from '@fastgpt/global/core/module/type';
import { ModuleInputKeyEnum } from '@fastgpt/global/core/module/constants';
import { streamFetch } from '@/web/common/api/fetch';

View File

@@ -2,13 +2,13 @@ import React, { useMemo } from 'react';
import { Flex, useTheme, Box } from '@chakra-ui/react';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import MyIcon from '@fastgpt/web/components/common/Icon';
import Tag from '@/components/Tag';
import Avatar from '@/components/Avatar';
import ToolMenu from './ToolMenu';
import type { ChatItemType } from '@fastgpt/global/core/chat/type';
import { useRouter } from 'next/router';
import { useTranslation } from 'next-i18next';
import { chatContentReplaceBlock } from '@fastgpt/global/core/chat/utils';
import { getChatTitleFromChatMessage } from '@fastgpt/global/core/chat/utils';
import FillTag from '@fastgpt/web/components/common/Tag/Fill';
const ChatHeader = ({
history,
@@ -33,10 +33,8 @@ const ChatHeader = ({
const { isPc } = useSystemStore();
const title = useMemo(
() =>
chatContentReplaceBlock(history[history.length - 2]?.value)?.slice(0, 8) ||
appName ||
t('core.chat.New Chat'),
[appName, history]
getChatTitleFromChatMessage(history[history.length - 2], appName || t('core.chat.New Chat')),
[appName, history, t]
);
return (
@@ -52,19 +50,19 @@ const ChatHeader = ({
<Box mr={3} color={'myGray.1000'}>
{title}
</Box>
<Tag>
<FillTag>
<MyIcon name={'history'} w={'14px'} />
<Box ml={1}>
{history.length === 0
? t('core.chat.New Chat')
: t('core.chat.History Amount', { amount: history.length })}
</Box>
</Tag>
</FillTag>
{!!chatModels && chatModels.length > 0 && (
<Tag ml={2} colorSchema={'green'}>
<FillTag ml={2} colorSchema={'green'}>
<MyIcon name={'core/chat/chatModelTag'} w={'14px'} />
<Box ml={1}>{chatModels.join(',')}</Box>
</Tag>
</FillTag>
)}
<Box flex={1} />
</>

View File

@@ -1,10 +1,11 @@
import React, { useMemo } from 'react';
import { useChatBox } from '@/components/ChatBox';
import { useChatBox } from '@/components/ChatBox/hooks/useChatBox';
import type { ChatItemType } from '@fastgpt/global/core/chat/type.d';
import { Menu, MenuButton, MenuList, MenuItem, Box } from '@chakra-ui/react';
import { Menu, MenuButton, MenuList, MenuItem, Box, IconButton } from '@chakra-ui/react';
import { useTranslation } from 'next-i18next';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { useRouter } from 'next/router';
import MyMenu from '@/components/MyMenu';
const ToolMenu = ({ history }: { history: ChatItemType[] }) => {
const { t } = useTranslation();
@@ -41,30 +42,21 @@ const ToolMenu = ({ history }: { history: ChatItemType[] }) => {
onClick: () => onExportChat({ type: 'pdf', history })
}
],
[history, onExportChat, router]
[history, onExportChat, router, t]
);
return history.length > 0 ? (
<Menu autoSelect={false} isLazy>
<MenuButton
_hover={{ bg: 'myWhite.600 ' }}
cursor={'pointer'}
borderRadius={'md'}
onClick={(e) => {
e.stopPropagation();
}}
>
<MyIcon name={'more'} w={'14px'} p={2} />
</MenuButton>
<MenuList color={'myGray.700'} minW={`120px !important`} zIndex={10}>
{menuList.map((item) => (
<MenuItem key={item.label} onClick={item.onClick} py={[2, 3]}>
<MyIcon name={item.icon as any} w={['14px', '16px']} />
<Box ml={[1, 2]}>{item.label}</Box>
</MenuItem>
))}
</MenuList>
</Menu>
<MyMenu
Button={
<IconButton
icon={<MyIcon name={'more'} w={'14px'} p={2} />}
aria-label={''}
size={'sm'}
variant={'whitePrimary'}
/>
}
menuList={menuList}
/>
) : (
<Box w={'28px'} h={'28px'} />
);

View File

@@ -22,7 +22,8 @@ const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 12);
import type { ChatHistoryItemType } from '@fastgpt/global/core/chat/type.d';
import { useTranslation } from 'next-i18next';
import ChatBox, { type ComponentRef, type StartChatFnProps } from '@/components/ChatBox';
import ChatBox from '@/components/ChatBox';
import type { ComponentRef, StartChatFnProps } from '@/components/ChatBox/type.d';
import PageContainer from '@/components/PageContainer';
import SideBar from '@/components/SideBar';
import ChatHistorySlider from './components/ChatHistorySlider';
@@ -33,8 +34,9 @@ import { useUserStore } from '@/web/support/user/useUserStore';
import { serviceSideProps } from '@/web/common/utils/i18n';
import { useAppStore } from '@/web/core/app/store/useAppStore';
import { checkChatSupportSelectFileByChatModels } from '@/web/core/chat/utils';
import { chatContentReplaceBlock } from '@fastgpt/global/core/chat/utils';
import { getChatTitleFromChatMessage } from '@fastgpt/global/core/chat/utils';
import { ChatStatusEnum } from '@fastgpt/global/core/chat/constants';
import { GPTMessages2Chats } from '@fastgpt/global/core/chat/adapt';
const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
const router = useRouter();
@@ -83,10 +85,7 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
abortCtrl: controller
});
const newTitle =
chatContentReplaceBlock(prompts[0].content).slice(0, 20) ||
prompts[1]?.value?.slice(0, 20) ||
t('core.chat.New Chat');
const newTitle = getChatTitleFromChatMessage(GPTMessages2Chats(prompts)[0]);
// new chat
if (completionChatId !== chatId) {
@@ -126,7 +125,7 @@ const Chat = ({ appId, chatId }: { appId: string; chatId: string }) => {
return { responseText, responseData, isNewChat: forbidRefresh.current };
},
[appId, chatId, histories, pushHistory, router, setChatData, t, updateHistory]
[appId, chatId, histories, pushHistory, router, setChatData, updateHistory]
);
useQuery(['loadModels'], () => loadMyApps(false));

View File

@@ -8,13 +8,14 @@ import { useQuery } from '@tanstack/react-query';
import { streamFetch } from '@/web/common/api/fetch';
import { useShareChatStore } from '@/web/core/chat/storeShareChat';
import SideBar from '@/components/SideBar';
import { gptMessage2ChatType } from '@/utils/adapt';
import { GPTMessages2Chats } from '@fastgpt/global/core/chat/adapt';
import { getErrText } from '@fastgpt/global/common/error/utils';
import type { ChatHistoryItemType, ChatSiteItemType } from '@fastgpt/global/core/chat/type.d';
import { customAlphabet } from 'nanoid';
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 12);
import ChatBox, { type ComponentRef, type StartChatFnProps } from '@/components/ChatBox';
import ChatBox from '@/components/ChatBox';
import type { ComponentRef, StartChatFnProps } from '@/components/ChatBox/type.d';
import PageContainer from '@/components/PageContainer';
import ChatHeader from './components/ChatHeader';
import ChatHistorySlider from './components/ChatHistorySlider';
@@ -22,9 +23,9 @@ import { serviceSideProps } from '@/web/common/utils/i18n';
import { checkChatSupportSelectFileByChatModels } from '@/web/core/chat/utils';
import { useTranslation } from 'next-i18next';
import { getInitOutLinkChatInfo } from '@/web/core/chat/api';
import { chatContentReplaceBlock } from '@fastgpt/global/core/chat/utils';
import { getChatTitleFromChatMessage } from '@fastgpt/global/core/chat/utils';
import { useChatStore } from '@/web/core/chat/storeChat';
import { ChatStatusEnum } from '@fastgpt/global/core/chat/constants';
import { ChatRoleEnum, ChatStatusEnum } from '@fastgpt/global/core/chat/constants';
import MyBox from '@/components/common/MyBox';
import { MongoOutLink } from '@fastgpt/service/support/outLink/schema';
import { OutLinkWithAppType } from '@fastgpt/global/support/outLink/type';
@@ -96,10 +97,7 @@ const OutLink = ({
abortCtrl: controller
});
const newTitle =
chatContentReplaceBlock(prompts[0].content).slice(0, 20) ||
prompts[1]?.value?.slice(0, 20) ||
t('core.chat.New Chat');
const newTitle = getChatTitleFromChatMessage(GPTMessages2Chats(prompts)[0]);
// new chat
if (completionChatId !== chatId) {
@@ -141,19 +139,17 @@ const OutLink = ({
}));
/* post message to report result */
const result: ChatSiteItemType[] = gptMessage2ChatType(prompts).map((item) => ({
const result: ChatSiteItemType[] = GPTMessages2Chats(prompts).map((item) => ({
...item,
status: 'finish'
}));
result[1].value = responseText;
result[1].responseData = responseData;
window.top?.postMessage(
{
type: 'shareChatFinish',
data: {
question: result[0]?.value,
answer: result[1]?.value
answer: responseText
}
},
'*'
@@ -166,7 +162,6 @@ const OutLink = ({
customVariables,
shareId,
outLinkUid,
t,
setChatData,
appId,
pushHistory,

View File

@@ -25,14 +25,16 @@ import { checkChatSupportSelectFileByChatModels } from '@/web/core/chat/utils';
import { useChatStore } from '@/web/core/chat/storeChat';
import { customAlphabet } from 'nanoid';
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 12);
import ChatBox, { type ComponentRef, type StartChatFnProps } from '@/components/ChatBox';
import ChatBox from '@/components/ChatBox';
import type { ComponentRef, StartChatFnProps } from '@/components/ChatBox/type.d';
import { streamFetch } from '@/web/common/api/fetch';
import type { ChatHistoryItemType } from '@fastgpt/global/core/chat/type.d';
import { chatContentReplaceBlock } from '@fastgpt/global/core/chat/utils';
import { getChatTitleFromChatMessage } from '@fastgpt/global/core/chat/utils';
import { ChatStatusEnum } from '@fastgpt/global/core/chat/constants';
import { getErrText } from '@fastgpt/global/common/error/utils';
import MyBox from '@/components/common/MyBox';
import SliderApps from './components/SliderApps';
import { GPTMessages2Chats } from '@fastgpt/global/core/chat/adapt';
const OutLink = ({
teamId,
@@ -85,10 +87,8 @@ const OutLink = ({
onMessage: generatingMessage,
abortCtrl: controller
});
const newTitle =
chatContentReplaceBlock(prompts[0].content).slice(0, 20) ||
prompts[1]?.value?.slice(0, 20) ||
t('core.chat.New Chat');
const newTitle = getChatTitleFromChatMessage(GPTMessages2Chats(prompts)[0]);
// new chat
if (completionChatId !== chatId) {
@@ -130,18 +130,7 @@ const OutLink = ({
return { responseText, responseData, isNewChat: forbidRefresh.current };
},
[
appId,
teamToken,
chatId,
histories,
pushHistory,
router,
setChatData,
teamId,
t,
updateHistory
]
[appId, teamToken, chatId, histories, pushHistory, router, setChatData, teamId, updateHistory]
);
/* replace router query to last chat */

View File

@@ -65,7 +65,7 @@ function DataProcess({
return list.filter(([key, value]) => {
if (feConfigs?.isPlus) return true;
return value.isPlus;
return value.openSource;
});
}, [feConfigs?.isPlus]);

View File

@@ -8,7 +8,7 @@ import MyIcon from '@fastgpt/web/components/common/Icon';
import { customAlphabet } from 'nanoid';
import { useRouter } from 'next/router';
import { Dispatch, useRef } from 'react';
import { useTranslation } from 'react-i18next';
import { useTranslation } from 'next-i18next';
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz1234567890', 8);
interface Props {

View File

@@ -4,7 +4,7 @@ import Header from './Header';
import Flow from '@/components/core/module/Flow';
import FlowProvider, { useFlowProviderStore } from '@/components/core/module/Flow/FlowProvider';
import { FlowModuleTemplateType } from '@fastgpt/global/core/module/type.d';
import { pluginSystemModuleTemplates } from '@/web/core/modules/template/system';
import { pluginSystemModuleTemplates } from '@fastgpt/global/core/module/template/constants';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/module/node/constant';
import { serviceSideProps } from '@/web/common/utils/i18n';
import { useQuery } from '@tanstack/react-query';