Compare commits

...

4 Commits

Author SHA1 Message Date
Archer
ba933c7450 perf: markdown code css (#2187) 2024-07-29 10:01:14 +08:00
Archer
856d7ce48f fix: app type (#2185) 2024-07-29 09:47:47 +08:00
Archer
23f22cda18 Add mongo forward read. Fix markdown code block. (#2174)
* perf: read from mongo forward node

* fix: code block ui

* perf: markdown code css
2024-07-29 09:47:30 +08:00
Archer
0a9a7691b4 Update 488.md 2024-07-26 13:50:42 +08:00
15 changed files with 204 additions and 128 deletions

View File

@@ -13,8 +13,8 @@ weight: 816
### 2. 修改镜像 ### 2. 修改镜像
- fastgpt 镜像 tag 修改成 v4.8.8-alpha - fastgpt 镜像 tag 修改成 v4.8.8-alpha2
- 商业版镜像 tag 修改成 v4.8.8-alpha - 商业版镜像 tag 修改成 v4.8.8-alpha2
### 3. 执行初始化 ### 3. 执行初始化

View File

@@ -31,6 +31,7 @@ const main = async (props: Props, retry = 3): Response => {
result: JSON.stringify(result) result: JSON.stringify(result)
}; };
} catch (error) { } catch (error) {
console.log(error);
if (retry <= 0) { if (retry <= 0) {
addLog.warn('DuckDuckGo error', { error }); addLog.warn('DuckDuckGo error', { error });
return { return {

View File

@@ -3,6 +3,7 @@ import { imageBaseUrl } from '@fastgpt/global/common/file/image/constants';
import { MongoImage } from './schema'; import { MongoImage } from './schema';
import { ClientSession } from '../../../common/mongo'; import { ClientSession } from '../../../common/mongo';
import { guessBase64ImageType } from '../utils'; import { guessBase64ImageType } from '../utils';
import { readFromSecondary } from '../../mongo/utils';
export function getMongoImgUrl(id: string, extension: string) { export function getMongoImgUrl(id: string, extension: string) {
return `${imageBaseUrl}${id}.${extension}`; return `${imageBaseUrl}${id}.${extension}`;
@@ -44,10 +45,13 @@ export async function uploadMongoImg({
export async function readMongoImg({ id }: { id: string }) { export async function readMongoImg({ id }: { id: string }) {
const formatId = id.replace(/\.[^/.]+$/, ''); const formatId = id.replace(/\.[^/.]+$/, '');
const data = await MongoImage.findById(formatId); const data = await MongoImage.findById(formatId, undefined, {
...readFromSecondary
});
if (!data) { if (!data) {
return Promise.reject('Image not found'); return Promise.reject('Image not found');
} }
return { return {
binary: data.binary, binary: data.binary,
mime: data.metadata?.mime ?? guessBase64ImageType(data.binary.toString('base64')) mime: data.metadata?.mime ?? guessBase64ImageType(data.binary.toString('base64'))

View File

@@ -1,4 +1,6 @@
import { ReadPreference } from './index';
export const readFromSecondary = { export const readFromSecondary = {
readPreference: 'secondaryPreferred', readPreference: ReadPreference.SECONDARY_PREFERRED, // primary | primaryPreferred | secondary | secondaryPreferred | nearest
readConcern: 'local' readConcern: 'local' as any // local | majority | linearizable | available
}; };

41
pnpm-lock.yaml generated
View File

@@ -61,7 +61,7 @@ importers:
version: 4.0.2 version: 4.0.2
next: next:
specifier: 14.2.5 specifier: 14.2.5
version: 14.2.5(@babel/core@7.24.9)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8) version: 14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8)
openai: openai:
specifier: 4.53.0 specifier: 4.53.0
version: 4.53.0(encoding@0.1.13) version: 4.53.0(encoding@0.1.13)
@@ -180,7 +180,7 @@ importers:
version: 1.4.5-lts.1 version: 1.4.5-lts.1
next: next:
specifier: 14.2.5 specifier: 14.2.5
version: 14.2.5(@babel/core@7.24.9)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8) version: 14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8)
nextjs-cors: nextjs-cors:
specifier: ^2.2.0 specifier: ^2.2.0
version: 2.2.0(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8)) version: 2.2.0(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8))
@@ -10036,7 +10036,7 @@ snapshots:
'@chakra-ui/react': 2.8.1(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@chakra-ui/react': 2.8.1(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(framer-motion@9.1.7(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@emotion/cache': 11.11.0 '@emotion/cache': 11.11.0
'@emotion/react': 11.11.1(@types/react@18.3.1)(react@18.3.1) '@emotion/react': 11.11.1(@types/react@18.3.1)(react@18.3.1)
next: 14.2.5(@babel/core@7.24.9)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8) next: 14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8)
react: 18.3.1 react: 18.3.1
'@chakra-ui/number-input@2.1.1(@chakra-ui/system@2.6.1(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(react@18.3.1))(react@18.3.1)': '@chakra-ui/number-input@2.1.1(@chakra-ui/system@2.6.1(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@emotion/styled@11.11.0(@emotion/react@11.11.1(@types/react@18.3.1)(react@18.3.1))(@types/react@18.3.1)(react@18.3.1))(react@18.3.1))(react@18.3.1)':
@@ -16652,7 +16652,7 @@ snapshots:
hoist-non-react-statics: 3.3.2 hoist-non-react-statics: 3.3.2
i18next: 23.11.5 i18next: 23.11.5
i18next-fs-backend: 2.3.1 i18next-fs-backend: 2.3.1
next: 14.2.5(@babel/core@7.24.9)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8) next: 14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8)
react: 18.3.1 react: 18.3.1
react-i18next: 14.1.2(i18next@23.11.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) react-i18next: 14.1.2(i18next@23.11.5)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -16682,10 +16682,36 @@ snapshots:
- '@babel/core' - '@babel/core'
- babel-plugin-macros - babel-plugin-macros
next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8):
dependencies:
'@next/env': 14.2.5
'@swc/helpers': 0.5.5
busboy: 1.6.0
caniuse-lite: 1.0.30001642
graceful-fs: 4.2.11
postcss: 8.4.31
react: 18.3.1
react-dom: 18.3.1(react@18.3.1)
styled-jsx: 5.1.1(react@18.3.1)
optionalDependencies:
'@next/swc-darwin-arm64': 14.2.5
'@next/swc-darwin-x64': 14.2.5
'@next/swc-linux-arm64-gnu': 14.2.5
'@next/swc-linux-arm64-musl': 14.2.5
'@next/swc-linux-x64-gnu': 14.2.5
'@next/swc-linux-x64-musl': 14.2.5
'@next/swc-win32-arm64-msvc': 14.2.5
'@next/swc-win32-ia32-msvc': 14.2.5
'@next/swc-win32-x64-msvc': 14.2.5
sass: 1.77.8
transitivePeerDependencies:
- '@babel/core'
- babel-plugin-macros
nextjs-cors@2.2.0(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8)): nextjs-cors@2.2.0(next@14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8)):
dependencies: dependencies:
cors: 2.8.5 cors: 2.8.5
next: 14.2.5(@babel/core@7.24.9)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8) next: 14.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(sass@1.77.8)
nextjs-node-loader@1.1.5(webpack@5.92.1): nextjs-node-loader@1.1.5(webpack@5.92.1):
dependencies: dependencies:
@@ -18058,6 +18084,11 @@ snapshots:
optionalDependencies: optionalDependencies:
'@babel/core': 7.24.9 '@babel/core': 7.24.9
styled-jsx@5.1.1(react@18.3.1):
dependencies:
client-only: 0.0.1
react: 18.3.1
stylis@4.2.0: {} stylis@4.2.0: {}
stylis@4.3.2: {} stylis@4.3.2: {}

View File

@@ -287,18 +287,18 @@ const codeLight: { [key: string]: React.CSSProperties } = {
const CodeLight = ({ const CodeLight = ({
children, children,
className, className,
inline, codeBlock,
match match
}: { }: {
children: React.ReactNode & React.ReactNode[]; children: React.ReactNode & React.ReactNode[];
className?: string; className?: string;
inline?: boolean; codeBlock?: boolean;
match: RegExpExecArray | null; match: RegExpExecArray | null;
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const { copyData } = useCopyData(); const { copyData } = useCopyData();
if (!inline) { if (codeBlock) {
const codeBoxName = useMemo(() => { const codeBoxName = useMemo(() => {
const input = match?.['input'] || ''; const input = match?.['input'] || '';
if (!input) return match?.[1]; if (!input) return match?.[1];
@@ -312,7 +312,6 @@ const CodeLight = ({
my={3} my={3}
borderRadius={'md'} borderRadius={'md'}
overflow={'overlay'} overflow={'overlay'}
bg={'myGray.900'}
boxShadow={ boxShadow={
'0px 0px 1px 0px rgba(19, 51, 107, 0.08), 0px 1px 2px 0px rgba(19, 51, 107, 0.05)' '0px 0px 1px 0px rgba(19, 51, 107, 0.08), 0px 1px 2px 0px rgba(19, 51, 107, 0.05)'
} }

View File

@@ -336,7 +336,7 @@
} }
.markdown pre code, .markdown pre code,
.markdown pre tt { .markdown pre tt {
background-color: transparent; background-color: transparent !important;
border: medium none; border: medium none;
} }
.markdown hr { .markdown hr {
@@ -360,13 +360,12 @@
margin: 0; margin: 0;
border: none; border: none;
border-radius: 0; border-radius: 0;
background-color: #292b33 !important; background-color: var(--chakra-colors-gray-900) !important;
overflow-x: auto; overflow-x: auto;
color: #fff; color: #fff;
} }
pre code { pre code {
background-color: #292b33 !important;
width: 100%; width: 100%;
} }

View File

@@ -36,7 +36,7 @@ const Markdown = ({
const components = useMemo<any>( const components = useMemo<any>(
() => ({ () => ({
img: Image, img: Image,
pre: 'div', pre: RewritePre,
p: (pProps: any) => <p {...pProps} dir="auto" />, p: (pProps: any) => <p {...pProps} dir="auto" />,
code: Code, code: Code,
a: A a: A
@@ -70,8 +70,7 @@ export default React.memo(Markdown);
/* Custom dom */ /* Custom dom */
const Code = React.memo(function Code(e: any) { const Code = React.memo(function Code(e: any) {
const { inline, className, children } = e; const { className, codeBlock, children } = e;
const match = /language-(\w+)/.exec(className || ''); const match = /language-(\w+)/.exec(className || '');
const codeType = match?.[1]; const codeType = match?.[1];
@@ -92,11 +91,11 @@ const Code = React.memo(function Code(e: any) {
} }
return ( return (
<CodeLight className={className} inline={inline} match={match}> <CodeLight className={className} codeBlock={codeBlock} match={match}>
{children} {children}
</CodeLight> </CodeLight>
); );
}, [codeType, className, inline, match, children, strChildren]); }, [codeType, className, codeBlock, match, children, strChildren]);
return Component; return Component;
}); });
@@ -149,3 +148,15 @@ const A = React.memo(function A({ children, ...props }: any) {
return <Link {...props}>{children}</Link>; return <Link {...props}>{children}</Link>;
}); });
function RewritePre({ children }: any) {
const modifiedChildren = React.Children.map(children, (child) => {
if (React.isValidElement(child)) {
// @ts-ignore
return React.cloneElement(child, { codeBlock: true });
}
return child;
});
return <>{modifiedChildren}</>;
}

View File

@@ -98,7 +98,7 @@ ${JSON.stringify(questionGuides)}`;
<AccordionPanel <AccordionPanel
py={0} py={0}
px={0} px={0}
mt={0} mt={3}
borderRadius={'md'} borderRadius={'md'}
overflow={'hidden'} overflow={'hidden'}
maxH={'500px'} maxH={'500px'}
@@ -111,10 +111,12 @@ ${toolParams}`}
/> />
)} )}
{toolResponse && ( {toolResponse && (
<Markdown <Box mt={3}>
source={`~~~json#Response <Markdown
source={`~~~json#Response
${toolResponse}`} ${toolResponse}`}
/> />
</Box>
)} )}
</AccordionPanel> </AccordionPanel>
</AccordionItem> </AccordionItem>

View File

@@ -9,6 +9,7 @@ import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { ChatItemCollectionName } from '@fastgpt/service/core/chat/chatItemSchema'; import { ChatItemCollectionName } from '@fastgpt/service/core/chat/chatItemSchema';
import { NextAPI } from '@/service/middleware/entry'; import { NextAPI } from '@/service/middleware/entry';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant'; import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
import { readFromSecondary } from '@fastgpt/service/common/mongo/utils';
async function handler( async function handler(
req: NextApiRequest, req: NextApiRequest,
@@ -39,101 +40,106 @@ async function handler(
}; };
const [data, total] = await Promise.all([ const [data, total] = await Promise.all([
MongoChat.aggregate([ MongoChat.aggregate(
{ $match: where }, [
{ { $match: where },
$sort: { {
userBadFeedbackCount: -1, $sort: {
userGoodFeedbackCount: -1, userBadFeedbackCount: -1,
customFeedbacksCount: -1, userGoodFeedbackCount: -1,
updateTime: -1 customFeedbacksCount: -1,
} updateTime: -1
}, }
{ $skip: (pageNum - 1) * pageSize }, },
{ $limit: pageSize }, { $skip: (pageNum - 1) * pageSize },
{ { $limit: pageSize },
$lookup: { {
from: ChatItemCollectionName, $lookup: {
let: { chatId: '$chatId' }, from: ChatItemCollectionName,
pipeline: [ let: { chatId: '$chatId' },
{ pipeline: [
$match: { {
$expr: { $match: {
$and: [ $expr: {
{ $eq: ['$appId', new Types.ObjectId(appId)] }, $and: [
{ $eq: ['$chatId', '$$chatId'] } { $eq: ['$appId', new Types.ObjectId(appId)] },
] { $eq: ['$chatId', '$$chatId'] }
]
}
}
},
{
$project: {
userGoodFeedback: 1,
userBadFeedback: 1,
customFeedbacks: 1,
adminFeedback: 1
}
}
],
as: 'chatitems'
}
},
{
$addFields: {
userGoodFeedbackCount: {
$size: {
$filter: {
input: '$chatitems',
as: 'item',
cond: { $ifNull: ['$$item.userGoodFeedback', false] }
} }
} }
}, },
{ userBadFeedbackCount: {
$project: { $size: {
userGoodFeedback: 1, $filter: {
userBadFeedback: 1, input: '$chatitems',
customFeedbacks: 1, as: 'item',
adminFeedback: 1 cond: { $ifNull: ['$$item.userBadFeedback', false] }
}
} }
} },
], customFeedbacksCount: {
as: 'chatitems' $size: {
} $filter: {
}, input: '$chatitems',
{ as: 'item',
$addFields: { cond: { $gt: [{ $size: { $ifNull: ['$$item.customFeedbacks', []] } }, 0] }
userGoodFeedbackCount: { }
$size: {
$filter: {
input: '$chatitems',
as: 'item',
cond: { $ifNull: ['$$item.userGoodFeedback', false] }
} }
} },
}, markCount: {
userBadFeedbackCount: { $size: {
$size: { $filter: {
$filter: { input: '$chatitems',
input: '$chatitems', as: 'item',
as: 'item', cond: { $ifNull: ['$$item.adminFeedback', false] }
cond: { $ifNull: ['$$item.userBadFeedback', false] } }
}
}
},
customFeedbacksCount: {
$size: {
$filter: {
input: '$chatitems',
as: 'item',
cond: { $gt: [{ $size: { $ifNull: ['$$item.customFeedbacks', []] } }, 0] }
}
}
},
markCount: {
$size: {
$filter: {
input: '$chatitems',
as: 'item',
cond: { $ifNull: ['$$item.adminFeedback', false] }
} }
} }
} }
},
{
$project: {
_id: 1,
id: '$chatId',
title: 1,
source: 1,
time: '$updateTime',
messageCount: { $size: '$chatitems' },
userGoodFeedbackCount: 1,
userBadFeedbackCount: 1,
customFeedbacksCount: 1,
markCount: 1
}
} }
}, ],
{ {
$project: { ...readFromSecondary
_id: 1,
id: '$chatId',
title: 1,
source: 1,
time: '$updateTime',
messageCount: { $size: '$chatitems' },
userGoodFeedbackCount: 1,
userBadFeedbackCount: 1,
customFeedbacksCount: 1,
markCount: 1
}
} }
]), ),
MongoChat.countDocuments(where) MongoChat.countDocuments(where, { ...readFromSecondary })
]); ]);
return { return {

View File

@@ -11,6 +11,7 @@ import {
import { NextAPI } from '@/service/middleware/entry'; import { NextAPI } from '@/service/middleware/entry';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant'; import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common'; import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
import { readFromSecondary } from '@fastgpt/service/common/mongo/utils';
async function handler(req: NextApiRequest, res: NextApiResponse<any>) { async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
let { datasetId } = req.query as { let { datasetId } = req.query as {
@@ -53,7 +54,10 @@ async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
teamId, teamId,
datasetId: { $in: datasets.map((d) => d._id) } datasetId: { $in: datasets.map((d) => d._id) }
}, },
'q a' 'q a',
{
...readFromSecondary
}
) )
.limit(50000) .limit(50000)
.cursor(); .cursor();

View File

@@ -4,6 +4,7 @@ import { authDataset } from '@fastgpt/service/support/permission/dataset/auth';
import { MongoDatasetData } from '@fastgpt/service/core/dataset/data/schema'; import { MongoDatasetData } from '@fastgpt/service/core/dataset/data/schema';
import { MongoDatasetTraining } from '@fastgpt/service/core/dataset/training/schema'; import { MongoDatasetTraining } from '@fastgpt/service/core/dataset/training/schema';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant'; import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { readFromSecondary } from '@fastgpt/service/common/mongo/utils';
export type getDatasetTrainingQueueResponse = { export type getDatasetTrainingQueueResponse = {
rebuildingCount: number; rebuildingCount: number;
@@ -24,8 +25,18 @@ async function handler(
}); });
const [rebuildingCount, trainingCount] = await Promise.all([ const [rebuildingCount, trainingCount] = await Promise.all([
MongoDatasetData.countDocuments({ rebuilding: true, teamId, datasetId }), MongoDatasetData.countDocuments(
MongoDatasetTraining.countDocuments({ teamId, datasetId }) { rebuilding: true, teamId, datasetId },
{
...readFromSecondary
}
),
MongoDatasetTraining.countDocuments(
{ teamId, datasetId },
{
...readFromSecondary
}
)
]); ]);
return { return {

View File

@@ -3,6 +3,7 @@ import { MongoDatasetTraining } from '@fastgpt/service/core/dataset/training/sch
import { authCert } from '@fastgpt/service/support/permission/auth/common'; import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { GetTrainingQueueProps } from '@/global/core/dataset/api'; import { GetTrainingQueueProps } from '@/global/core/dataset/api';
import { NextAPI } from '@/service/middleware/entry'; import { NextAPI } from '@/service/middleware/entry';
import { readFromSecondary } from '@fastgpt/service/common/mongo/utils';
async function handler(req: NextApiRequest) { async function handler(req: NextApiRequest) {
await authCert({ req, authToken: true }); await authCert({ req, authToken: true });
@@ -10,20 +11,25 @@ async function handler(req: NextApiRequest) {
// get queue data // get queue data
// 分别统计 model = vectorModel和agentModel的数量 // 分别统计 model = vectorModel和agentModel的数量
const data = await MongoDatasetTraining.aggregate([ const data = await MongoDatasetTraining.aggregate(
{ [
$match: { {
lockTime: { $lt: new Date('2040/1/1') }, $match: {
$or: [{ model: { $eq: vectorModel } }, { model: { $eq: agentModel } }] lockTime: { $lt: new Date('2040/1/1') },
$or: [{ model: { $eq: vectorModel } }, { model: { $eq: agentModel } }]
}
},
{
$group: {
_id: '$model',
count: { $sum: 1 }
}
} }
}, ],
{ {
$group: { ...readFromSecondary
_id: '$model',
count: { $sum: 1 }
}
} }
]); );
const vectorTrainingCount = data.find((item) => item._id === vectorModel)?.count || 0; const vectorTrainingCount = data.find((item) => item._id === vectorModel)?.count || 0;
const agentTrainingCount = data.find((item) => item._id === agentModel)?.count || 0; const agentTrainingCount = data.find((item) => item._id === agentModel)?.count || 0;

View File

@@ -14,7 +14,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
throw new Error('url is empty'); throw new Error('url is empty');
} }
if (!FastGPTProUrl) { if (!FastGPTProUrl) {
throw new Error('未配置商业版链接'); throw new Error(`未配置商业版链接: ${path}`);
} }
const parsedUrl = new URL(FastGPTProUrl); const parsedUrl = new URL(FastGPTProUrl);

View File

@@ -11,7 +11,7 @@ import { useContextSelector } from 'use-context-selector';
import { ChatContext } from '@/web/core/chat/context/chatContext'; import { ChatContext } from '@/web/core/chat/context/chatContext';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip'; import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import { InitChatResponse } from '@/global/core/chat/api'; import { InitChatResponse } from '@/global/core/chat/api';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants'; import { AppFolderTypeList, AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { useSystem } from '@fastgpt/web/hooks/useSystem'; import { useSystem } from '@fastgpt/web/hooks/useSystem';
import LightRowTabs from '@fastgpt/web/components/common/Tabs/LightRowTabs'; import LightRowTabs from '@fastgpt/web/components/common/Tabs/LightRowTabs';
import { useRouter } from 'next/router'; import { useRouter } from 'next/router';
@@ -92,7 +92,7 @@ const MobileDrawer = ({
id: item._id, id: item._id,
name: item.name, name: item.name,
avatar: item.avatar, avatar: item.avatar,
isFolder: item.type === AppTypeEnum.folder isFolder: AppFolderTypeList.includes(item.type)
})) }))
); );
}, []); }, []);