System plugin (#2091)

* System template (#2082)

* feat: system plugin (#2024)

* add plugin cost & change plugin avatar (#2030)

* add plugin cost & change plugin avatar

* add author

* feat: duckduckgo plugin

* duckduck search

* perf: templates select system plugin

* perf: system plugin avatar

* feat: duckduck plugins

* doc

* perf: plugin classify

* perf: icon avatar component

* perf: system template avatar

---------

Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>

* feat: system plugin search

* perf: plugin packages important

* perf: source avatar

* nextconfig

* perf: i18n

* perf: default model

* perf: system plugin author

---------

Co-authored-by: heheer <71265218+newfish-cmyk@users.noreply.github.com>
This commit is contained in:
Archer
2024-07-19 14:15:01 +08:00
committed by GitHub
parent 1eedb9caba
commit cf7145ab54
165 changed files with 2643 additions and 557 deletions

View File

@@ -1,22 +0,0 @@
import React from 'react';
import { Image } from '@chakra-ui/react';
import type { ImageProps } from '@chakra-ui/react';
import { LOGO_ICON } from '@fastgpt/global/common/system/constants';
const Avatar = ({ w = '30px', src, ...props }: ImageProps) => {
return (
<Image
fallbackSrc={LOGO_ICON}
fallbackStrategy={'onError'}
// borderRadius={'md'}
objectFit={'contain'}
alt=""
w={w}
h={w}
src={src || LOGO_ICON}
{...props}
/>
);
};
export default Avatar;

View File

@@ -6,7 +6,7 @@ import { useChatStore } from '@/web/core/chat/context/storeChat';
import { HUMAN_ICON } from '@fastgpt/global/common/system/constants';
import NextLink from 'next/link';
import Badge from '../Badge';
import Avatar from '../Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { useTranslation } from 'next-i18next';
import { useSystemStore } from '@/web/common/system/useSystemStore';

View File

@@ -7,7 +7,7 @@ import { AI_POINT_USAGE_CARD_ROUTE } from '@/web/support/wallet/sub/constants';
import MySelect, { SelectProps } from '@fastgpt/web/components/common/MySelect';
import { HUGGING_FACE_ICON, LOGO_ICON } from '@fastgpt/global/common/system/constants';
import { Box, Flex } from '@chakra-ui/react';
import Avatar from '../Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
type Props = SelectProps & {

View File

@@ -10,7 +10,7 @@ import { MongoImageTypeEnum } from '@fastgpt/global/common/file/image/constants'
import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
import { getErrText } from '@fastgpt/global/common/error/utils';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import { useToast } from '@fastgpt/web/hooks/useToast';
export type EditResourceInfoFormType = {
@@ -80,10 +80,10 @@ const EditResourceModal = ({
<HStack spacing={4}>
<MyTooltip label={t('common:common.Set Avatar')}>
<Avatar
flexShrink={0}
flex={'0 0 2rem'}
src={avatar}
w={['28px', '32px']}
h={['28px', '32px']}
w={'2rem'}
h={'2rem'}
cursor={'pointer'}
borderRadius={'md'}
onClick={onOpenSelectFile}

View File

@@ -7,7 +7,7 @@ import {
} from '@fastgpt/global/common/parentFolder/type';
import MyIcon from '@fastgpt/web/components/common/Icon';
import Loading from '@fastgpt/web/components/common/MyLoading';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { useMemoizedFn } from 'ahooks';
import { FolderImgUrl } from '@fastgpt/global/common/file/image/constants';
@@ -135,7 +135,12 @@ const SelectOneResource = ({
/>
</Flex>
)}
<Avatar ml={index !== 0 ? '0.5rem' : 0} src={item.avatar} w={'1.25rem'} />
<Avatar
ml={index !== 0 ? '0.5rem' : 0}
src={item.avatar}
w={'1.25rem'}
borderRadius={'sm'}
/>
<Box fontSize={['md', 'sm']} ml={2} className="textEllipsis">
{item.name}
</Box>

View File

@@ -4,7 +4,7 @@ import { LLMModelTypeEnum, llmModelTypeFilterMap } from '@fastgpt/global/core/ai
import { Box, Button, Flex, css, useDisclosure } from '@chakra-ui/react';
import type { SettingAIDataType } from '@fastgpt/global/core/app/type.d';
import AISettingModal from '@/components/core/ai/AISettingModal';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import { HUGGING_FACE_ICON } from '@fastgpt/global/common/system/constants';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import { useTranslation } from 'next-i18next';

View File

@@ -10,7 +10,7 @@ import {
Grid,
Divider
} from '@chakra-ui/react';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import type { SelectedDatasetType } from '@fastgpt/global/core/workflow/api.d';
import { useToast } from '@fastgpt/web/hooks/useToast';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';

View File

@@ -0,0 +1,24 @@
import { Box, Flex, Divider } from '@chakra-ui/react';
import React from 'react';
import { useTranslation } from 'next-i18next';
const CoseTooltip = ({ cost }: { cost?: number }) => {
const { t } = useTranslation();
return (
<>
<Divider mt={4} mb={2} />
<Flex>
<Box>{t('common:core.plugin.cost')}</Box>
<Box color={'myGray.600'}>
{cost && cost > 0
? t('app:plugin_cost_per_times', {
cost: cost
})
: t('common:core.plugin.Free')}
</Box>
</Flex>
</>
);
};
export default CoseTooltip;

View File

@@ -1,4 +1,4 @@
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import { Box } from '@chakra-ui/react';
import { useTheme } from '@chakra-ui/system';
import React from 'react';

View File

@@ -1,7 +1,7 @@
import React, { useState } from 'react';
import { ModalBody, useTheme, ModalFooter, Button, Box, Card, Flex, Grid } from '@chakra-ui/react';
import { useTranslation } from 'next-i18next';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { DatasetTypeEnum } from '@fastgpt/global/core/dataset/constants';
import DatasetSelectModal, { useDatasetSelect } from '@/components/core/dataset/SelectModal';

View File

@@ -46,7 +46,7 @@ export const useChat = () => {
for (const key in data) {
variablesForm.setValue(key, '');
}
console.log(ChatBoxRef.current);
ChatBoxRef.current?.restartChat?.();
}, [variablesForm]);

View File

@@ -15,7 +15,7 @@ import {
} from '@fastgpt/global/core/chat/type';
import React from 'react';
import MyIcon from '@fastgpt/web/components/common/Icon';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
type props = {
value: UserChatItemValueItemType | AIChatItemValueItemType;
@@ -81,12 +81,14 @@ ${JSON.stringify(questionGuides)}`;
borderWidth={'1px'}
borderColor={'myGray.200'}
boxShadow={'1'}
pl={3}
pr={2.5}
_hover={{
bg: 'auto'
}}
>
<Avatar src={tool.toolAvatar} w={'1rem'} h={'1rem'} mr={2} />
<Box mr={1} fontSize={'sm'}>
<Avatar src={tool.toolAvatar} w={'1.25rem'} h={'1.25rem'} borderRadius={'sm'} />
<Box mx={2} fontSize={'sm'} color={'myGray.900'}>
{tool.toolName}
</Box>
{isChatting && !tool.response && <MyIcon name={'common/loading'} w={'14px'} />}

View File

@@ -12,6 +12,7 @@ import { DatasetSearchModeMap } from '@fastgpt/global/core/dataset/constants';
import { formatNumber } from '@fastgpt/global/common/math/tools';
import { useI18n } from '@/web/context/I18n';
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
import Avatar from '@fastgpt/web/components/common/Avatar';
function RowRender({
children,
@@ -125,18 +126,18 @@ export const ResponseBox = React.memo(function ResponseBox({
() =>
response.map((item, i) => ({
label: (
<Flex alignItems={'center'} justifyContent={'center'} px={2}>
<Image
mr={2}
<Flex alignItems={'center'} justifyContent={'center'} px={2} py={1}>
<Avatar
src={
item.moduleLogo ||
moduleTemplatesFlat.find((template) => item.moduleType === template.flowNodeType)
?.avatar
}
alt={''}
w={['14px', '16px']}
w={'1.25rem'}
borderRadius={'sm'}
/>
{t(item.moduleName as any)}
<Box ml={1.5}> {t(item.moduleName as any)}</Box>
</Flex>
),
value: `${i}`
@@ -334,7 +335,9 @@ export const ResponseBox = React.memo(function ResponseBox({
<Row
label={t('common:core.chat.response.Plugin response detail')}
rawDom={
<ResponseBox response={activeModule.pluginDetail} showDetail={showDetail} />
<Box h={'60vh'}>
<ResponseBox response={activeModule.pluginDetail} showDetail={showDetail} />
</Box>
}
/>
)}
@@ -350,7 +353,11 @@ export const ResponseBox = React.memo(function ResponseBox({
{activeModule?.toolDetail && activeModule?.toolDetail.length > 0 && (
<Row
label={t('common:core.chat.response.Tool call response detail')}
rawDom={<ResponseBox response={activeModule.toolDetail} showDetail={showDetail} />}
rawDom={
<Box h={'60vh'}>
<ResponseBox response={activeModule.toolDetail} showDetail={showDetail} />
</Box>
}
/>
)}

View File

@@ -4,7 +4,7 @@ import { useTranslation } from 'next-i18next';
import { PermissionValueType } from '@fastgpt/global/support/permission/type';
import CollaboratorContextProvider, { MemberManagerInputPropsType } from '../MemberManager/context';
import { Box, Button, Flex, HStack, ModalBody } from '@chakra-ui/react';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import DefaultPermissionList from '../DefaultPerList';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';

View File

@@ -14,7 +14,7 @@ import {
import MyModal from '@fastgpt/web/components/common/MyModal';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { useContextSelector } from 'use-context-selector';
import MyAvatar from '@/components/Avatar';
import MyAvatar from '@fastgpt/web/components/common/Avatar';
import { useMemo, useState } from 'react';
import PermissionSelect from './PermissionSelect';
import PermissionTags from './PermissionTags';
@@ -23,7 +23,7 @@ import { useUserStore } from '@/web/support/user/useUserStore';
import { getTeamMembers } from '@/web/support/user/team/api';
import MyBox from '@fastgpt/web/components/common/MyBox';
import { ChevronDownIcon } from '@chakra-ui/icons';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import { useRequest, useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { useTranslation } from 'next-i18next';

View File

@@ -15,7 +15,7 @@ import React from 'react';
import { useContextSelector } from 'use-context-selector';
import PermissionSelect from './PermissionSelect';
import PermissionTags from './PermissionTags';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import { CollaboratorContext } from './context';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { useRequest, useRequest2 } from '@fastgpt/web/hooks/useRequest';

View File

@@ -4,7 +4,7 @@ import React from 'react';
import { useContextSelector } from 'use-context-selector';
import { CollaboratorContext } from './context';
import Tag, { TagProps } from '@fastgpt/web/components/common/Tag';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import { useTranslation } from 'next-i18next';
export type MemberListCardProps = BoxProps & { tagStyle?: Omit<TagProps, 'children'> };

View File

@@ -1,5 +1,5 @@
import { Box, Button, Flex, IconButton, Text } from '@chakra-ui/react';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import { useTranslation } from 'next-i18next';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { TeamMemberRoleEnum } from '@fastgpt/global/support/user/team/constant';

View File

@@ -9,7 +9,7 @@ import { useRequest } from '@fastgpt/web/hooks/useRequest';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { Box, Button, Flex, Input, ModalBody, ModalFooter } from '@chakra-ui/react';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import { postCreateTeam, putUpdateTeam } from '@/web/support/user/team/api';
import { CreateTeamProps } from '@fastgpt/global/support/user/team/controller.d';
import { MongoImageTypeEnum } from '@fastgpt/global/common/file/image/constants';

View File

@@ -1,4 +1,4 @@
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MyIcon from '@fastgpt/web/components/common/Icon';
import {
Box,

View File

@@ -12,7 +12,7 @@ import {
InputGroup,
InputLeftElement
} from '@chakra-ui/react';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MyModal from '@fastgpt/web/components/common/MyModal';
import React, { useMemo, useState } from 'react';
import { useTranslation } from 'next-i18next';

View File

@@ -3,7 +3,7 @@ import { Box, Button, Flex, Tag, TagLabel, useDisclosure } from '@chakra-ui/reac
import { useTranslation } from 'next-i18next';
import { useContextSelector } from 'use-context-selector';
import MyIcon from '@fastgpt/web/components/common/Icon';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import { useRequest } from '@fastgpt/web/hooks/useRequest';
import { delMemberPermission } from '@/web/support/user/team/api';
import { useUserStore } from '@/web/support/user/useUserStore';

View File

@@ -6,7 +6,7 @@ import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import dynamic from 'next/dynamic';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { useToast } from '@fastgpt/web/hooks/useToast';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
const TeamManageModal = dynamic(() => import('../TeamManageModal'));

View File

@@ -13,7 +13,7 @@ import {
import { useQuery } from '@tanstack/react-query';
import { getTeamList, updateInviteResult } from '@/web/support/user/team/api';
import { TeamMemberStatusEnum } from '@fastgpt/global/support/user/team/constant';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import { useRequest } from '@fastgpt/web/hooks/useRequest';
import { useToast } from '@fastgpt/web/hooks/useToast';
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';

View File

@@ -23,7 +23,7 @@ import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
import { compressImgFileAndUpload } from '@/web/common/file/controller';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { useTranslation } from 'next-i18next';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MyIcon from '@fastgpt/web/components/common/Icon';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import { useRouter } from 'next/router';

View File

@@ -27,7 +27,7 @@ import { useTranslation } from 'next-i18next';
import { useQuery } from '@tanstack/react-query';
import { useUserStore } from '@/web/support/user/useUserStore';
import { getTeamMembers } from '@/web/support/user/team/api';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MySelect from '@fastgpt/web/components/common/MySelect';
import { formatNumber } from '@fastgpt/global/common/math/tools';
import EmptyTip from '@fastgpt/web/components/common/EmptyTip';

View File

@@ -1,26 +1,55 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import type { NextApiResponse } from 'next';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { NodeTemplateListItemType } from '@fastgpt/global/core/workflow/type/node.d';
import { NextAPI } from '@/service/middleware/entry';
import { getCommunityPluginsTemplateList } from '@fastgpt/plugins/register';
import { getSystemPluginTemplates } from '@fastgpt/plugins/register';
import { FlowNodeTemplateTypeEnum } from '@fastgpt/global/core/workflow/constants';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import { ParentIdType } from '@fastgpt/global/common/parentFolder/type';
import { ApiRequestProps } from '@fastgpt/service/type/next';
import { replaceRegChars } from '@fastgpt/global/common/string/tools';
export type GetSystemPluginTemplatesBody = {
searchKey?: string;
parentId: ParentIdType;
};
async function handler(
req: NextApiRequest,
req: ApiRequestProps<GetSystemPluginTemplatesBody>,
res: NextApiResponse<any>
): Promise<NodeTemplateListItemType[]> {
await authCert({ req, authToken: true });
// const data: NodeTemplateListItemType[] =
// global.communityPlugins?.map((plugin) => ({
// id: plugin.id,
// templateType: plugin.templateType ?? FlowNodeTemplateTypeEnum.other,
// flowNodeType: FlowNodeTypeEnum.pluginModule,
// avatar: plugin.avatar,
// name: plugin.name,
// intro: plugin.intro
// })) || [];
const { searchKey, parentId } = req.body;
return getCommunityPluginsTemplateList();
const formatParentId = parentId || null;
return getSystemPluginTemplates().then((res) =>
res
// Just show the active plugins
.filter((item) => item.isActive)
.map<NodeTemplateListItemType>((plugin) => ({
id: plugin.id,
isFolder: plugin.isFolder,
parentId: plugin.parentId,
templateType: plugin.templateType ?? FlowNodeTemplateTypeEnum.other,
flowNodeType: FlowNodeTypeEnum.pluginModule,
avatar: plugin.avatar,
name: plugin.name,
intro: plugin.intro,
isTool: plugin.isTool,
currentCost: plugin.currentCost,
author: plugin.author
}))
.filter((item) => {
if (searchKey) {
if (item.isFolder) return false;
const regx = new RegExp(`${replaceRegChars(searchKey)}`, 'i');
return regx.test(item.name) || regx.test(item.intro || '');
}
return item.parentId === formatParentId;
})
);
}
export default NextAPI(handler);

View File

@@ -0,0 +1,35 @@
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry';
import { ParentIdType, ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type';
import { getSystemPluginTemplates } from '@fastgpt/plugins/register';
export type pathQuery = {
parentId: ParentIdType;
};
export type pathBody = {};
export type pathResponse = Promise<ParentTreePathItemType[]>;
async function handler(
req: ApiRequestProps<pathBody, pathQuery>,
res: ApiResponseType<any>
): Promise<pathResponse> {
const { parentId } = req.query;
if (!parentId) return [];
const plugins = await getSystemPluginTemplates();
const plugin = plugins.find((item) => item.id === parentId);
if (!plugin) return [];
return [
{
parentId: plugin.id,
parentName: plugin.name
}
];
}
export default NextAPI(handler);

View File

@@ -30,7 +30,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
});
const response = await ai.chat.completions.create({
model: 'gpt-3.5-turbo',
model: 'gpt-4o-mini',
max_tokens: 1,
messages: [{ role: 'user', content: 'hi' }]
});

View File

@@ -16,7 +16,7 @@ import { useSelectFile } from '@/web/common/file/hooks/useSelectFile';
import { compressImgFileAndUpload } from '@/web/common/file/controller';
import { getErrText } from '@fastgpt/global/common/error/utils';
import { useRequest, useRequest2 } from '@fastgpt/web/hooks/useRequest';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
import { MongoImageTypeEnum } from '@fastgpt/global/common/file/image/constants';

View File

@@ -13,7 +13,7 @@ import {
import { useRouter } from 'next/router';
import { AppSchema } from '@fastgpt/global/core/app/type.d';
import { useTranslation } from 'next-i18next';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MyIcon from '@fastgpt/web/components/common/Icon';
import TagsEditModal from '../TagsEditModal';
import { useSystemStore } from '@/web/common/system/useSystemStore';

View File

@@ -18,7 +18,7 @@ import { useDatasetStore } from '@/web/core/dataset/store/dataset';
import dynamic from 'next/dynamic';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MyIcon from '@fastgpt/web/components/common/Icon';
import VariableEdit from '@/components/core/app/VariableEdit';
import PromptEditor from '@fastgpt/web/components/common/Textarea/PromptEditor';
@@ -242,8 +242,15 @@ const EditForm = ({
})
}
>
<Avatar src={item.avatar} w={'18px'} mr={1} />
<Box flex={'1 0 0'} w={0} className={'textEllipsis'} fontSize={'sm'}>
<Avatar src={item.avatar} w={'1.5rem'} borderRadius={'sm'} />
<Box
ml={2}
flex={'1 0 0'}
w={0}
className={'textEllipsis'}
fontSize={'sm'}
color={'myGray.900'}
>
{item.name}
</Box>
</Flex>
@@ -292,8 +299,15 @@ const EditForm = ({
borderColor: 'primary.300'
}}
>
<Avatar src={item.avatar} w={'1rem'} mr={1} />
<Box flex={'1 0 0'} w={0} className={'textEllipsis'} fontSize={'sm'}>
<Avatar src={item.avatar} w={'1.5rem'} borderRadius={'sm'} />
<Box
ml={2}
flex={'1 0 0'}
w={0}
className={'textEllipsis'}
fontSize={'sm'}
color={'myGray.900'}
>
{item.name}
</Box>
<DeleteIcon

View File

@@ -1,4 +1,4 @@
import React, { useCallback, useMemo, useState } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
@@ -26,21 +26,27 @@ import {
FlowNodeTemplateType,
NodeTemplateListItemType
} from '@fastgpt/global/core/workflow/type/node.d';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { AddIcon } from '@chakra-ui/icons';
import { getPreviewPluginNode, getSystemPlugTemplates } from '@/web/core/app/api/plugin';
import {
getPreviewPluginNode,
getSystemPlugTemplates,
getSystemPluginPaths
} from '@/web/core/app/api/plugin';
import MyBox from '@fastgpt/web/components/common/MyBox';
import { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants';
import { useForm } from 'react-hook-form';
import JsonEditor from '@fastgpt/web/components/common/Textarea/JsonEditor';
import { FlowNodeInputTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
import { getTeamPlugTemplates } from '@/web/core/app/api/plugin';
import { ParentIdType } from '@fastgpt/global/common/parentFolder/type';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { getAppFolderPath } from '@/web/core/app/api/app';
import FolderPath from '@/components/common/folder/Path';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import CoseTooltip from '@/components/core/app/plugin/CoseTooltip';
import { useSystemStore } from '@/web/common/system/useSystemStore';
type Props = {
selectedTools: FlowNodeTemplateType[];
@@ -63,9 +69,7 @@ const ToolSelectModal = ({ onClose, ...props }: Props & { onClose: () => void })
const { data: templates = [], loading: isLoading } = useRequest2(
async () => {
if (templateType === TemplateTypeEnum.systemPlugin) {
return (await getSystemPlugTemplates()).filter(
(item) => item.isTool && item.name.toLowerCase().includes(searchKey.toLowerCase())
);
return getSystemPlugTemplates({ parentId, searchKey });
} else if (templateType === TemplateTypeEnum.teamPlugin) {
return getTeamPlugTemplates({
parentId,
@@ -82,10 +86,20 @@ const ToolSelectModal = ({ onClose, ...props }: Props & { onClose: () => void })
}
);
const { data: paths = [] } = useRequest2(() => getAppFolderPath(parentId), {
manual: false,
refreshDeps: [parentId]
});
const { data: paths = [] } = useRequest2(
() => {
if (templateType === TemplateTypeEnum.teamPlugin) return getAppFolderPath(parentId);
return getSystemPluginPaths(parentId);
},
{
manual: false,
refreshDeps: [parentId]
}
);
useEffect(() => {
setParentId('');
}, [templateType, searchKey]);
return (
<MyModal
@@ -129,7 +143,7 @@ const ToolSelectModal = ({ onClose, ...props }: Props & { onClose: () => void })
</InputGroup>
</Box>
{/* route components */}
{templateType === TemplateTypeEnum.teamPlugin && !searchKey && parentId && (
{!searchKey && parentId && (
<Flex mt={2} px={[3, 6]}>
<FolderPath
paths={paths}
@@ -145,6 +159,7 @@ const ToolSelectModal = ({ onClose, ...props }: Props & { onClose: () => void })
templates={templates}
isLoadingData={isLoading}
setParentId={setParentId}
showCost={templateType === TemplateTypeEnum.systemPlugin}
{...props}
/>
</MyBox>
@@ -160,13 +175,16 @@ const RenderList = React.memo(function RenderList({
isLoadingData,
onAddTool,
onRemoveTool,
setParentId
setParentId,
showCost
}: Props & {
templates: NodeTemplateListItemType[];
isLoadingData: boolean;
setParentId: React.Dispatch<React.SetStateAction<ParentIdType>>;
showCost?: boolean;
}) {
const { t } = useTranslation();
const { feConfigs } = useSystemStore();
const [configTool, setConfigTool] = useState<FlowNodeTemplateType>();
const onCloseConfigTool = useCallback(() => setConfigTool(undefined), []);
@@ -195,57 +213,78 @@ const RenderList = React.memo(function RenderList({
const selected = selectedTools.some((tool) => tool.pluginId === item.id);
return (
<Flex
<MyTooltip
key={item.id}
alignItems={'center'}
p={[4, 5]}
_notLast={{
borderBottomWidth: '1px',
borderBottomColor: 'myGray.150'
}}
_hover={{
bg: 'myGray.50'
}}
placement={'bottom'}
shouldWrapChildren={false}
label={
<Box>
<Flex alignItems={'center'}>
<Avatar
src={item.avatar}
w={'1.75rem'}
objectFit={'contain'}
borderRadius={'sm'}
/>
<Box fontWeight={'bold'} ml={2} color={'myGray.900'}>
{t(item.name as any)}
</Box>
</Flex>
<Box mt={2} color={'myGray.500'}>
{t(item.intro as any) || t('common:core.workflow.Not intro')}
</Box>
{showCost && <CoseTooltip cost={item.currentCost} />}
</Box>
}
>
<Avatar
src={item.avatar}
w={['26px', '32px']}
objectFit={'contain'}
borderRadius={'0'}
/>
<Box ml={5} flex={'1 0 0'}>
<Box color={'black'}>{t(item.name as any)}</Box>
{item.intro && (
<Box className="textEllipsis3" color={'myGray.500'} fontSize={'xs'}>
{t(item.intro as any)}
<Flex
alignItems={'center'}
position={'relative'}
p={[4, 5]}
_notLast={{
borderBottomWidth: '1px',
borderBottomColor: 'myGray.150'
}}
_hover={{
bg: 'myGray.50'
}}
>
<Avatar src={item.avatar} w={'2rem'} objectFit={'contain'} borderRadius={'md'} />
<Box ml={3} flex={'1 0 0'} color={'myGray.900'}>
{t(item.name as any)}
</Box>
{item.author !== undefined && (
<Box fontSize={'xs'} mr={3}>
{`by ${item.author || feConfigs.systemTitle}`}
</Box>
)}
</Box>
{selected ? (
<Button
size={'sm'}
variant={'grayDanger'}
leftIcon={<MyIcon name={'delete'} w={'14px'} />}
onClick={() => onRemoveTool(item)}
>
{t('common:common.Remove')}
</Button>
) : item.isFolder ? (
<Button size={'sm'} variant={'whiteBase'} onClick={() => setParentId(item.id)}>
{t('common:common.Open')}
</Button>
) : (
<Button
size={'sm'}
variant={'whiteBase'}
leftIcon={<AddIcon fontSize={'10px'} />}
isLoading={isLoading}
onClick={() => onClickAdd(item)}
>
{t('common:common.Add')}
</Button>
)}
</Flex>
{selected ? (
<Button
size={'sm'}
variant={'grayDanger'}
leftIcon={<MyIcon name={'delete'} w={'14px'} />}
onClick={() => onRemoveTool(item)}
>
{t('common:common.Remove')}
</Button>
) : item.isFolder ? (
<Button size={'sm'} variant={'whiteBase'} onClick={() => setParentId(item.id)}>
{t('common:common.Open')}
</Button>
) : (
<Button
size={'sm'}
variant={'whiteBase'}
leftIcon={<AddIcon fontSize={'10px'} />}
isLoading={isLoading}
onClick={() => onClickAdd(item)}
>
{t('common:common.Add')}
</Button>
)}
</Flex>
</MyTooltip>
);
})}
{!!configTool && (

View File

@@ -10,7 +10,6 @@ import { WorkflowContext, getWorkflowStore } from '../WorkflowComponents/context
import { useInterval } from 'ahooks';
import { AppContext, TabEnum } from '../context';
import RouteTab from '../RouteTab';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import PopoverConfirm from '@fastgpt/web/components/common/MyPopover/PopoverConfirm';
import { useRouter } from 'next/router';

View File

@@ -4,7 +4,7 @@ import { useContextSelector } from 'use-context-selector';
import { AppContext, TabEnum } from '../context';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import { useTranslation } from 'next-i18next';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MyMenu from '@fastgpt/web/components/common/MyMenu';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { useI18n } from '@/web/context/I18n';
@@ -159,7 +159,7 @@ const AppCard = ({ showSaveStatus }: { showSaveStatus: boolean }) => {
return (
<HStack>
<InfoMenu>
<Avatar src={appDetail.avatar} w={'1.75rem'} />
<Avatar src={appDetail.avatar} w={'1.75rem'} borderRadius={'md'} />
</InfoMenu>
<Box>
<InfoMenu>

View File

@@ -1,17 +1,30 @@
import React, { useCallback, useMemo, useState } from 'react';
import { Box, Flex, IconButton, Input, InputGroup, InputLeftElement, css } from '@chakra-ui/react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import {
Box,
Divider,
Flex,
IconButton,
Input,
InputGroup,
InputLeftElement,
css
} from '@chakra-ui/react';
import type {
NodeTemplateListItemType,
NodeTemplateListType
} from '@fastgpt/global/core/workflow/type/node.d';
import { useViewport, XYPosition } from 'reactflow';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import { nodeTemplate2FlowNode } from '@/web/core/workflow/utils';
import { useTranslation } from 'next-i18next';
import EmptyTip from '@fastgpt/web/components/common/EmptyTip';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import { getPreviewPluginNode, getSystemPlugTemplates } from '@/web/core/app/api/plugin';
import {
getPreviewPluginNode,
getSystemPlugTemplates,
getSystemPluginPaths
} from '@/web/core/app/api/plugin';
import { useToast } from '@fastgpt/web/hooks/useToast';
import { getErrText } from '@fastgpt/global/common/error/utils';
import { workflowNodeTemplateList } from '@fastgpt/web/core/workflow/constants';
@@ -33,6 +46,7 @@ import { useWorkflowUtils } from './hooks/useUtils';
import { moduleTemplatesFlat } from '@fastgpt/global/core/workflow/template/constants';
import { cloneDeep } from 'lodash';
import { useSystem } from '@fastgpt/web/hooks/useSystem';
import CoseTooltip from '@/components/core/app/plugin/CoseTooltip';
type ModuleTemplateListProps = {
isOpen: boolean;
@@ -40,6 +54,7 @@ type ModuleTemplateListProps = {
};
type RenderListProps = {
templates: NodeTemplateListItemType[];
type: TemplateTypeEnum;
onClose: () => void;
parentId: ParentIdType;
setParentId: React.Dispatch<React.SetStateAction<ParentIdType>>;
@@ -51,7 +66,7 @@ enum TemplateTypeEnum {
'teamPlugin' = 'teamPlugin'
}
const sliderWidth = 390;
const sliderWidth = 420;
const NodeTemplatesModal = ({ isOpen, onClose }: ModuleTemplateListProps) => {
const { t } = useTranslation();
@@ -104,7 +119,7 @@ const NodeTemplatesModal = ({ isOpen, onClose }: ModuleTemplateListProps) => {
refreshDeps: [basicNodeTemplates, nodeList, hasToolNode, templateType, searchKey, parentId]
}
);
const { data: teamApps, loading: isLoadingTeamApp } = useRequest2(
const { data: teamAndSystemApps, loading: isLoadingTeamApp } = useRequest2(
async () => {
if (templateType === TemplateTypeEnum.teamPlugin) {
return getTeamPlugTemplates({
@@ -113,6 +128,12 @@ const NodeTemplatesModal = ({ isOpen, onClose }: ModuleTemplateListProps) => {
type: [AppTypeEnum.folder, AppTypeEnum.httpPlugin, AppTypeEnum.plugin]
}).then((res) => res.filter((app) => app.id !== appId));
}
if (templateType === TemplateTypeEnum.systemPlugin) {
return getSystemPlugTemplates({
searchKey,
parentId
});
}
},
{
manual: false,
@@ -120,29 +141,28 @@ const NodeTemplatesModal = ({ isOpen, onClose }: ModuleTemplateListProps) => {
refreshDeps: [templateType, searchKey, parentId]
}
);
const { data: systemPlugins, loading: isLoadingSystemPlugins } = useRequest2(
async () => {
if (templateType === TemplateTypeEnum.systemPlugin) {
return getSystemPlugTemplates();
}
const isLoading = isLoadingTeamApp;
const templates = useMemo(
() => basicNodes || teamAndSystemApps || [],
[basicNodes, teamAndSystemApps]
);
useEffect(() => {
setParentId('');
}, [templateType, searchKey]);
const { data: paths = [] } = useRequest2(
() => {
if (templateType === TemplateTypeEnum.teamPlugin) return getAppFolderPath(parentId);
return getSystemPluginPaths(parentId);
},
{
manual: false,
refreshDeps: [templateType]
refreshDeps: [parentId]
}
);
const isLoading = isLoadingTeamApp || isLoadingSystemPlugins;
const templates = useMemo(
() => basicNodes || teamApps || systemPlugins || [],
[basicNodes, systemPlugins, teamApps]
);
const { data: paths = [] } = useRequest2(() => getAppFolderPath(parentId), {
manual: false,
refreshDeps: [parentId]
});
const Render = useMemo(() => {
return (
<>
@@ -154,6 +174,7 @@ const NodeTemplatesModal = ({ isOpen, onClose }: ModuleTemplateListProps) => {
left={0}
bottom={0}
w={`${sliderWidth}px`}
maxW={'100%'}
onClick={onClose}
fontSize={'sm'}
/>
@@ -176,30 +197,35 @@ const NodeTemplatesModal = ({ isOpen, onClose }: ModuleTemplateListProps) => {
userSelect={'none'}
overflow={isOpen ? 'none' : 'hidden'}
>
{/* Header */}
<Box pl={'20px'} mb={3} pr={'10px'} whiteSpace={'nowrap'} overflow={'hidden'}>
{/* Tabs */}
<Flex flex={'1 0 0'} alignItems={'center'} gap={3}>
<FillRowTabs
list={[
{
icon: 'core/modules/basicNode',
label: t('common:core.module.template.Basic Node'),
value: TemplateTypeEnum.basic
},
{
icon: 'core/modules/systemPlugin',
label: t('common:core.module.template.System Plugin'),
value: TemplateTypeEnum.systemPlugin
},
{
icon: 'core/modules/teamPlugin',
label: t('common:core.module.template.Team Plugin'),
value: TemplateTypeEnum.teamPlugin
}
]}
py={'5px'}
value={templateType}
onChange={(e) => setTemplateType(e as TemplateTypeEnum)}
/>
<Box flex={'1 0 0'}>
<FillRowTabs
list={[
{
icon: 'core/modules/basicNode',
label: t('core.module.template.Basic Node'),
value: TemplateTypeEnum.basic
},
{
icon: 'core/modules/systemPlugin',
label: t('core.module.template.System Plugin'),
value: TemplateTypeEnum.systemPlugin
},
{
icon: 'core/modules/teamPlugin',
label: t('core.module.template.Team Plugin'),
value: TemplateTypeEnum.teamPlugin
}
]}
width={'100%'}
py={'5px'}
value={templateType}
onChange={(e) => setTemplateType(e as TemplateTypeEnum)}
/>
</Box>
{/* close icon */}
<IconButton
size={'sm'}
@@ -210,7 +236,9 @@ const NodeTemplatesModal = ({ isOpen, onClose }: ModuleTemplateListProps) => {
onClick={onClose}
/>
</Flex>
{templateType === TemplateTypeEnum.teamPlugin && (
{/* Search */}
{(templateType === TemplateTypeEnum.teamPlugin ||
templateType === TemplateTypeEnum.systemPlugin) && (
<Flex mt={2} alignItems={'center'} h={10}>
<InputGroup mr={4} h={'full'}>
<InputLeftElement h={'full'} alignItems={'center'} display={'flex'}>
@@ -224,28 +252,52 @@ const NodeTemplatesModal = ({ isOpen, onClose }: ModuleTemplateListProps) => {
/>
</InputGroup>
<Box flex={1} />
<Flex
alignItems={'center'}
cursor={'pointer'}
_hover={{
color: 'primary.600'
}}
fontSize={'sm'}
onClick={() => router.push('/app/list')}
>
<Box></Box>
<MyIcon name={'common/rightArrowLight'} w={'14px'} />
{templateType === TemplateTypeEnum.teamPlugin && (
<Flex
alignItems={'center'}
cursor={'pointer'}
_hover={{
color: 'primary.600'
}}
fontSize={'sm'}
onClick={() => router.push('/app/list')}
gap={1}
>
<Box></Box>
<MyIcon name={'common/rightArrowLight'} w={'0.8rem'} />
</Flex>
)}
{templateType === TemplateTypeEnum.systemPlugin &&
feConfigs.systemPluginCourseUrl && (
<Flex
alignItems={'center'}
cursor={'pointer'}
_hover={{
color: 'primary.600'
}}
fontSize={'sm'}
onClick={() => window.open(feConfigs.systemPluginCourseUrl)}
gap={1}
>
<Box></Box>
<MyIcon name={'common/rightArrowLight'} w={'0.8rem'} />
</Flex>
)}
</Flex>
)}
{/* paths */}
{(templateType === TemplateTypeEnum.teamPlugin ||
templateType === TemplateTypeEnum.systemPlugin) &&
!searchKey &&
parentId && (
<Flex alignItems={'center'} mt={2}>
<FolderPath paths={paths} FirstPathDom={null} onClick={setParentId} />
</Flex>
</Flex>
)}
{templateType === TemplateTypeEnum.teamPlugin && !searchKey && parentId && (
<Flex alignItems={'center'} mt={2}>
<FolderPath paths={paths} FirstPathDom={null} onClick={setParentId} />
</Flex>
)}
)}
</Box>
<RenderList
templates={templates}
type={templateType}
onClose={onClose}
parentId={parentId}
setParentId={setParentId}
@@ -262,14 +314,18 @@ export default React.memo(NodeTemplatesModal);
const RenderList = React.memo(function RenderList({
templates,
type,
onClose,
parentId,
setParentId
}: RenderListProps) {
const { t } = useTranslation();
const { appT } = useI18n();
const { feConfigs } = useSystemStore();
const { isPc } = useSystem();
const isSystemPlugin = type === TemplateTypeEnum.systemPlugin;
const { x, y, zoom } = useViewport();
const { setLoading } = useSystemStore();
const { toast } = useToast();
@@ -337,7 +393,7 @@ const RenderList = React.memo(function RenderList({
flowNodeType: templateNode.flowNodeType,
pluginId: templateNode.pluginId
}),
intro: t(templateNode.intro || ('' as any))
intro: t(templateNode.intro as any)
},
position: { x: mouseX, y: mouseY - 20 },
selected: true
@@ -371,9 +427,9 @@ const RenderList = React.memo(function RenderList({
}
})}
>
{item.label && (
{item.label && formatTemplates.length > 1 && (
<Flex>
<Box fontSize={'sm'} fontWeight={'bold'} flex={1}>
<Box fontSize={'sm'} fontWeight={'500'} flex={1} color={'myGray.900'}>
{t(item.label as any)}
</Box>
</Flex>
@@ -385,27 +441,29 @@ const RenderList = React.memo(function RenderList({
key={template.id}
placement={'right'}
label={
<Box>
<Box py={2}>
<Flex alignItems={'center'}>
<Avatar
src={template.avatar}
w={'24px'}
w={'1.75rem'}
objectFit={'contain'}
borderRadius={'0'}
borderRadius={'sm'}
/>
<Box fontWeight={'bold'} ml={3}>
<Box fontWeight={'bold'} ml={3} color={'myGray.900'}>
{t(template.name as any)}
</Box>
</Flex>
<Box mt={2} color={'myGray.500'}>
{t(template.intro as any) || t('common:core.workflow.Not intro')}
</Box>
{isSystemPlugin && <CoseTooltip cost={template.currentCost} />}
</Box>
}
>
<Flex
alignItems={'center'}
p={5}
py={4}
px={3}
cursor={'pointer'}
_hover={{ bg: 'myWhite.600' }}
borderRadius={'sm'}
@@ -436,13 +494,24 @@ const RenderList = React.memo(function RenderList({
>
<Avatar
src={template.avatar}
w={'1.7rem'}
w={'2rem'}
objectFit={'contain'}
borderRadius={'0'}
borderRadius={'md'}
/>
<Box color={'black'} fontSize={'sm'} ml={5} flex={'1 0 0'}>
<Box
color={'myGray.900'}
fontWeight={'500'}
fontSize={'sm'}
ml={3}
flex={'1 0 0'}
>
{t(template.name as any)}
</Box>
{template.author !== undefined && (
<Box fontSize={'xs'} color={'myGray.500'}>
{`by ${template.author || feConfigs.systemTitle}`}
</Box>
)}
</Flex>
</MyTooltip>
))}
@@ -452,7 +521,17 @@ const RenderList = React.memo(function RenderList({
</Box>
</Box>
);
}, [appT, formatTemplates, isPc, onAddNode, onClose, setParentId, t, templates.length]);
}, [
appT,
formatTemplates,
isPc,
isSystemPlugin,
onAddNode,
onClose,
setParentId,
t,
templates.length
]);
return Render;
});

View File

@@ -1,7 +1,7 @@
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { Box, Button, Card, Flex } from '@chakra-ui/react';
import MyIcon from '@fastgpt/web/components/common/Icon';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import type { FlowNodeItemType } from '@fastgpt/global/core/workflow/type/node.d';
import { useTranslation } from 'next-i18next';
import { useEditTitle } from '@/web/common/hooks/useEditTitle';
@@ -137,7 +137,7 @@ const NodeCard = (props: Props) => {
{/* avatar and name */}
<Flex alignItems={'center'}>
<Avatar src={avatar} borderRadius={'0'} objectFit={'contain'} w={'30px'} h={'30px'} />
<Avatar src={avatar} borderRadius={'sm'} objectFit={'contain'} w={'30px'} h={'30px'} />
<Box ml={3} fontSize={'md'} fontWeight={'medium'}>
{t(name as any)}
</Box>

View File

@@ -19,7 +19,7 @@ import { AppContext } from '@/pages/app/detail/components/context';
const MultipleRowSelect = dynamic(
() => import('@fastgpt/web/components/common/MySelect/MultipleRowSelect')
);
const Avatar = dynamic(() => import('@/components/Avatar'));
const Avatar = dynamic(() => import('@fastgpt/web/components/common/Avatar'));
type SelectProps = {
value?: ReferenceValueProps;
@@ -120,8 +120,8 @@ export const useReference = ({
return {
label: (
<Flex alignItems={'center'}>
<Avatar mr={1} src={node.avatar} w={'14px'} borderRadius={'ms'} />
<Box>{t(node.name as any)}</Box>
<Avatar src={node.avatar} w={'1.25rem'} borderRadius={'xs'} />
<Box ml={1}>{t(node.name as any)}</Box>
</Flex>
),
value: node.nodeId,

View File

@@ -2,7 +2,7 @@ import React, { useMemo } from 'react';
import type { RenderInputProps } from '../type';
import { Box, Button, useDisclosure } from '@chakra-ui/react';
import { SelectAppItemType } from '@fastgpt/global/core/workflow/template/system/runApp/type';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import SelectAppModal from '../../../../SelectAppModal';
import { useTranslation } from 'next-i18next';
import { useContextSelector } from 'use-context-selector';

View File

@@ -3,7 +3,7 @@ import type { RenderInputProps } from '../type';
import { Box, Button, Flex, Grid, useDisclosure, useTheme } from '@chakra-ui/react';
import { useDatasetStore } from '@/web/core/dataset/store/dataset';
import { SelectedDatasetType } from '@fastgpt/global/core/workflow/api';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import { useQuery } from '@tanstack/react-query';
import { useTranslation } from 'next-i18next';
import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constants';

View File

@@ -18,9 +18,8 @@ import { useToast } from '@fastgpt/web/hooks/useToast';
import { postCreateApp } from '@/web/core/app/api';
import { useRouter } from 'next/router';
import { simpleBotTemplates, workflowTemplates, pluginTemplates } from '@/web/core/app/templates';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { useRequest } from '@fastgpt/web/hooks/useRequest';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { useTranslation } from 'next-i18next';
@@ -150,7 +149,7 @@ const CreateModal = ({ onClose, type }: { type: CreateAppType; onClose: () => vo
w={['28px', '32px']}
h={['28px', '32px']}
cursor={'pointer'}
borderRadius={'sm'}
borderRadius={'md'}
onClick={onOpenSelectFile}
/>
</MyTooltip>
@@ -195,7 +194,7 @@ const CreateModal = ({ onClose, type }: { type: CreateAppType; onClose: () => vo
}}
>
<Flex alignItems={'center'}>
<Avatar src={item.avatar} borderRadius={'md'} w={'20px'} />
<Avatar src={item.avatar} borderRadius={'md'} w={'1.5rem'} />
<Box ml={3} color={'myGray.900'}>
{t(item.name as any)}
</Box>

View File

@@ -21,7 +21,7 @@ import { compressImgFileAndUpload } from '@/web/common/file/controller';
import { getErrText } from '@fastgpt/global/common/error/utils';
import { useToast } from '@fastgpt/web/hooks/useToast';
import { useRequest } from '@fastgpt/web/hooks/useRequest';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import { useTranslation } from 'next-i18next';
import { HttpPluginImgUrl, MongoImageTypeEnum } from '@fastgpt/global/common/file/image/constants';

View File

@@ -4,7 +4,7 @@ import { useRouter } from 'next/router';
import { delAppById, putAppById, resumeInheritPer } from '@/web/core/app/api';
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
import MyIcon from '@fastgpt/web/components/common/Icon';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import PermissionIconText from '@/components/support/permission/IconText';
import { useI18n } from '@/web/context/I18n';
import EmptyTip from '@fastgpt/web/components/common/EmptyTip';

View File

@@ -2,7 +2,7 @@ import React 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 Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import ToolMenu from './ToolMenu';
import type { ChatItemType } from '@fastgpt/global/core/chat/type';
import { useTranslation } from 'next-i18next';

View File

@@ -3,7 +3,7 @@ import { Box, Button, Flex, useTheme, IconButton } from '@chakra-ui/react';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { useEditTitle } from '@/web/common/hooks/useEditTitle';
import { useRouter } from 'next/router';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { useTranslation } from 'next-i18next';
@@ -145,7 +145,7 @@ const ChatHistorySlider = ({
})
}
>
<Avatar src={appAvatar} />
<Avatar src={appAvatar} borderRadius={'md'} />
<Box flex={'1 0 0'} w={0} ml={2} fontWeight={'bold'} className={'textEllipsis'}>
{appName}
</Box>

View File

@@ -4,7 +4,7 @@ import { useMarkdown } from '@/web/common/hooks/useMarkdown';
import dynamic from 'next/dynamic';
const Markdown = dynamic(() => import('@/components/Markdown'));
const Avatar = dynamic(() => import('@/components/Avatar'));
const Avatar = dynamic(() => import('@fastgpt/web/components/common/Avatar'));
const Empty = ({
showChatProblem,

View File

@@ -3,7 +3,7 @@ import { Flex, Box, IconButton, HStack } from '@chakra-ui/react';
import { useRouter } from 'next/router';
import { useTranslation } from 'next-i18next';
import MyIcon from '@fastgpt/web/components/common/Icon';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import { AppListItemType } from '@fastgpt/global/core/app/type';
import MyDivider from '@fastgpt/web/components/common/MyDivider';
import MyPopover from '@fastgpt/web/components/common/MyPopover/index';
@@ -152,7 +152,7 @@ const SliderApps = ({ apps, activeAppId }: { apps: AppListItemType[]; activeAppI
onClick: () => onChangeApp(item._id)
})}
>
<Avatar src={item.avatar} w={'24px'} />
<Avatar src={item.avatar} w={'1.5rem'} borderRadius={'md'} />
<Box ml={2} className={'textEllipsis'}>
{item.name}
</Box>

View File

@@ -8,7 +8,7 @@ import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
import { useForm } from 'react-hook-form';
import { compressImgFileAndUpload } from '@/web/common/file/controller';
import type { DatasetItemType } from '@fastgpt/global/core/dataset/type.d';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import { useTranslation } from 'next-i18next';
import { useSystemStore } from '@/web/common/system/useSystemStore';

View File

@@ -2,7 +2,7 @@ import React, { useCallback } from 'react';
import { useTranslation } from 'next-i18next';
import { Box, Flex, IconButton, useTheme, Progress } from '@chakra-ui/react';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import { DatasetTypeMap } from '@fastgpt/global/core/dataset/constants';
import DatasetTypeTag from '@/components/core/dataset/DatasetTypeTag';
import MyIcon from '@fastgpt/web/components/common/Icon';

View File

@@ -8,7 +8,7 @@ import { useToast } from '@fastgpt/web/hooks/useToast';
import { useRouter } from 'next/router';
import { useSystemStore } from '@/web/common/system/useSystemStore';
import { useRequest } from '@fastgpt/web/hooks/useRequest';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import MyModal from '@fastgpt/web/components/common/MyModal';
import { postCreateDataset } from '@/web/core/dataset/api';

View File

@@ -8,7 +8,7 @@ import MyIcon from '@fastgpt/web/components/common/Icon';
import { useRouter } from 'next/router';
import PermissionIconText from '@/components/support/permission/IconText';
import DatasetTypeTag from '@/components/core/dataset/DatasetTypeTag';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import { useConfirm } from '@fastgpt/web/hooks/useConfirm';
import { useRequest } from '@fastgpt/web/hooks/useRequest';
import { DatasetItemType } from '@fastgpt/global/core/dataset/type';

View File

@@ -10,7 +10,7 @@ import {
useTheme,
Grid
} from '@chakra-ui/react';
import Avatar from '@/components/Avatar';
import Avatar from '@fastgpt/web/components/common/Avatar';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
import MyModal from '@fastgpt/web/components/common/MyModal';
import MyIcon from '@fastgpt/web/components/common/Icon';

View File

@@ -61,6 +61,7 @@ const defaultFeConfigs: FastGPTFeConfigsType = {
show_git: true,
docUrl: 'https://doc.fastgpt.in',
openAPIDocUrl: 'https://doc.fastgpt.in/docs/development/openapi',
systemPluginCourseUrl: 'https://fael3z0zfze.feishu.cn/wiki/ERZnw9R26iRRG0kXZRec6WL9nwh',
systemTitle: 'FastGPT',
concatMd:
'项目开源地址: [FastGPT GitHub](https://github.com/labring/FastGPT)\n交流群: ![](https://oss.laf.run/htr4n1-images/fastgpt-qr-code.jpg)',

View File

@@ -1,9 +1,12 @@
import { initSystemConfig } from '.';
import { createDatasetTrainingMongoWatch } from '@/service/core/dataset/training/utils';
import { getSystemPluginTemplates } from '@fastgpt/plugins/register';
import { MongoSystemConfigs } from '@fastgpt/service/common/system/config/schema';
import { MongoSystemPluginSchema } from '@fastgpt/service/core/app/plugin/systemPluginSchema';
export const startMongoWatch = async () => {
reloadConfigWatch();
refetchSystemPlugin();
createDatasetTrainingMongoWatch();
};
@@ -19,3 +22,13 @@ const reloadConfigWatch = () => {
} catch (error) {}
});
};
const refetchSystemPlugin = () => {
const changeStream = MongoSystemPluginSchema.watch();
changeStream.on('change', async (change) => {
try {
getSystemPluginTemplates(true);
} catch (error) {}
});
};

View File

@@ -12,8 +12,11 @@ import type { copyAppQuery, copyAppResponse } from '@/pages/api/core/app/copy';
export const postCreateAppFolder = (data: CreateAppFolderBody) =>
POST('/core/app/folder/create', data);
export const getAppFolderPath = (parentId: ParentIdType) =>
GET<ParentTreePathItemType[]>(`/core/app/folder/path`, { parentId });
export const getAppFolderPath = (parentId: ParentIdType) => {
if (!parentId) return Promise.resolve<ParentTreePathItemType[]>([]);
return GET<ParentTreePathItemType[]>(`/core/app/folder/path`, { parentId });
};
/* detail */
export const postTransition2Workflow = (data: transitionWorkflowBody) =>

View File

@@ -11,6 +11,8 @@ import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import { FlowNodeTemplateTypeEnum } from '@fastgpt/global/core/workflow/constants';
import type { GetPreviewNodeQuery } from '@/pages/api/core/app/plugin/getPreviewNode';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { ParentIdType, ParentTreePathItemType } from '@fastgpt/global/common/parentFolder/type';
import { GetSystemPluginTemplatesBody } from '@/pages/api/core/app/plugin/getSystemPluginTemplates';
/* ============ team plugin ============== */
export const getTeamPlugTemplates = (data?: ListAppBody) =>
@@ -30,8 +32,14 @@ export const getTeamPlugTemplates = (data?: ListAppBody) =>
}))
);
export const getSystemPlugTemplates = () =>
GET<NodeTemplateListItemType[]>('/core/app/plugin/getSystemPluginTemplates');
/* ============ system plugin ============== */
export const getSystemPlugTemplates = (data: GetSystemPluginTemplatesBody) =>
POST<NodeTemplateListItemType[]>('/core/app/plugin/getSystemPluginTemplates', data);
export const getSystemPluginPaths = (parentId: ParentIdType) => {
if (!parentId) return Promise.resolve<ParentTreePathItemType[]>([]);
return GET<ParentTreePathItemType[]>('/core/app/plugin/path', { parentId });
};
export const getPreviewPluginNode = (data: GetPreviewNodeQuery) =>
GET<FlowNodeTemplateType>('/core/app/plugin/getPreviewNode', data);

View File

@@ -22,7 +22,7 @@ type TemplateType = (AppItemType & {
export const simpleBotTemplates: TemplateType = [
{
id: 'simpleChat',
avatar: '/imgs/workflow/AI.png',
avatar: 'core/workflow/template/aiChat',
name: '简易机器人',
intro: '一个极其简单的 AI 应用,你可以绑定知识库或工具。',
type: AppTypeEnum.simple,
@@ -31,7 +31,7 @@ export const simpleBotTemplates: TemplateType = [
nodeId: 'userGuide',
name: '系统配置',
intro: '可以配置应用的系统参数',
avatar: '/imgs/workflow/userGuide.png',
avatar: 'core/workflow/template/systemConfig',
flowNodeType: FlowNodeTypeEnum.systemConfig,
position: {
x: 531.2422736065552,
@@ -94,7 +94,7 @@ export const simpleBotTemplates: TemplateType = [
nodeId: '448745',
name: '流程开始',
intro: '',
avatar: '/imgs/workflow/userChatInput.svg',
avatar: 'core/workflow/template/workflowStart',
flowNodeType: FlowNodeTypeEnum.workflowStart,
position: {
x: 558.4082376415505,
@@ -125,7 +125,7 @@ export const simpleBotTemplates: TemplateType = [
nodeId: 'loOvhld2ZTKa',
name: 'AI 对话',
intro: 'AI 大模型对话',
avatar: '/imgs/workflow/AI.png',
avatar: 'core/workflow/template/aiChat',
flowNodeType: FlowNodeTypeEnum.chatNode,
showStatus: true,
position: {
@@ -142,7 +142,7 @@ export const simpleBotTemplates: TemplateType = [
],
label: 'core.module.input.label.aiModel',
valueType: WorkflowIOValueTypeEnum.string,
value: 'gpt-3.5-turbo'
value: 'gpt-4o-mini'
},
{
key: 'temperature',
@@ -252,7 +252,7 @@ export const simpleBotTemplates: TemplateType = [
},
{
id: 'chatGuide',
avatar: '/imgs/workflow/userGuide.png',
avatar: 'core/workflow/template/systemConfig',
name: '对话引导 + 变量',
intro: '可以在对话开始发送一段提示,或者让用户填写一些内容,作为本次对话的变量',
type: AppTypeEnum.simple,
@@ -261,7 +261,7 @@ export const simpleBotTemplates: TemplateType = [
nodeId: 'userGuide',
name: '系统配置',
intro: '可以配置应用的系统参数',
avatar: '/imgs/workflow/userGuide.png',
avatar: 'core/workflow/template/systemConfig',
flowNodeType: FlowNodeTypeEnum.systemConfig,
position: {
x: 496.57560693988853,
@@ -341,7 +341,7 @@ export const simpleBotTemplates: TemplateType = [
nodeId: '448745',
name: '流程开始',
intro: '',
avatar: '/imgs/workflow/userChatInput.svg',
avatar: 'core/workflow/template/workflowStart',
flowNodeType: FlowNodeTypeEnum.workflowStart,
position: {
x: 558.4082376415505,
@@ -372,7 +372,7 @@ export const simpleBotTemplates: TemplateType = [
nodeId: 'loOvhld2ZTKa',
name: 'AI 对话',
intro: 'AI 大模型对话',
avatar: '/imgs/workflow/AI.png',
avatar: 'core/workflow/template/aiChat',
flowNodeType: FlowNodeTypeEnum.chatNode,
showStatus: true,
position: {
@@ -389,7 +389,7 @@ export const simpleBotTemplates: TemplateType = [
],
label: 'core.module.input.label.aiModel',
valueType: WorkflowIOValueTypeEnum.string,
value: 'gpt-3.5-turbo'
value: 'gpt-4o-mini'
},
{
key: 'temperature',
@@ -499,7 +499,7 @@ export const simpleBotTemplates: TemplateType = [
},
{
id: 'simpleDatasetChat',
avatar: '/imgs/workflow/db.png',
avatar: 'core/workflow/template/datasetSearch',
name: '知识库+对话引导',
intro: '每次提问时进行一次知识库搜索,将搜索结果注入 LLM 模型进行参考回答',
type: AppTypeEnum.simple,
@@ -508,7 +508,7 @@ export const simpleBotTemplates: TemplateType = [
nodeId: 'userGuide',
name: '系统配置',
intro: '可以配置应用的系统参数',
avatar: '/imgs/workflow/userGuide.png',
avatar: 'core/workflow/template/systemConfig',
flowNodeType: FlowNodeTypeEnum.systemConfig,
position: {
x: 531.2422736065552,
@@ -571,7 +571,7 @@ export const simpleBotTemplates: TemplateType = [
nodeId: 'workflowStartNodeId',
name: '流程开始',
intro: '',
avatar: '/imgs/workflow/userChatInput.svg',
avatar: 'core/workflow/template/workflowStart',
flowNodeType: FlowNodeTypeEnum.workflowStart,
position: {
x: 558.4082376415505,
@@ -602,7 +602,7 @@ export const simpleBotTemplates: TemplateType = [
nodeId: '7BdojPlukIQw',
name: 'AI 对话',
intro: 'AI 大模型对话',
avatar: '/imgs/workflow/AI.png',
avatar: 'core/workflow/template/aiChat',
flowNodeType: FlowNodeTypeEnum.chatNode,
showStatus: true,
position: {
@@ -619,7 +619,7 @@ export const simpleBotTemplates: TemplateType = [
],
label: 'core.module.input.label.aiModel',
valueType: WorkflowIOValueTypeEnum.string,
value: 'gpt-3.5-turbo'
value: 'gpt-4o-mini'
},
{
key: 'temperature',
@@ -722,7 +722,7 @@ export const simpleBotTemplates: TemplateType = [
nodeId: 'iKBoX2vIzETU',
name: '知识库搜索',
intro: '调用“语义检索”和“全文检索”能力,从“知识库”中查找可能与问题相关的参考内容',
avatar: '/imgs/workflow/db.png',
avatar: 'core/workflow/template/datasetSearch',
flowNodeType: FlowNodeTypeEnum.datasetSearchNode,
showStatus: true,
position: {
@@ -827,7 +827,7 @@ export const simpleBotTemplates: TemplateType = [
},
{
id: 'toolChat',
avatar: '/imgs/workflow/history.png',
avatar: 'core/workflow/template/getTime',
name: '知道时间的机器人',
intro: '通过挂载时间插件,让模型获取当前最新时间',
type: AppTypeEnum.simple,
@@ -836,7 +836,7 @@ export const simpleBotTemplates: TemplateType = [
nodeId: 'userGuide',
name: '系统配置',
intro: '可以配置应用的系统参数',
avatar: '/imgs/workflow/userGuide.png',
avatar: 'core/workflow/template/systemConfig',
flowNodeType: FlowNodeTypeEnum.systemConfig,
position: {
x: 531.2422736065552,
@@ -850,7 +850,7 @@ export const simpleBotTemplates: TemplateType = [
nodeId: 'workflowStartNodeId',
name: '流程开始',
intro: '',
avatar: '/imgs/workflow/userChatInput.svg',
avatar: 'core/workflow/template/workflowStart',
flowNodeType: FlowNodeTypeEnum.workflowStart,
position: {
x: 558.4082376415505,
@@ -881,7 +881,7 @@ export const simpleBotTemplates: TemplateType = [
nodeId: 'jrWPV9',
name: '工具调用',
intro: '通过AI模型自动选择一个或多个功能块进行调用也可以对插件进行调用。',
avatar: '/imgs/workflow/tool.svg',
avatar: 'core/workflow/template/toolCall',
flowNodeType: FlowNodeTypeEnum.tools,
showStatus: true,
position: {
@@ -896,7 +896,7 @@ export const simpleBotTemplates: TemplateType = [
label: 'core.module.input.label.aiModel',
valueType: 'string',
llmModelType: 'all',
value: 'gpt-3.5-turbo'
value: 'gpt-4o-mini'
},
{
key: 'temperature',
@@ -963,7 +963,7 @@ export const simpleBotTemplates: TemplateType = [
nodeId: 'zBxjo5',
name: '获取当前时间',
intro: '获取用户当前时区的时间。',
avatar: '/imgs/workflow/getCurrentTime.svg',
avatar: 'core/workflow/template/getTime',
flowNodeType: 'pluginModule',
showStatus: false,
position: {
@@ -1021,7 +1021,7 @@ export const workflowTemplates: TemplateType = [
nodeId: 'userGuide',
name: '系统配置',
intro: '可以配置应用的系统参数',
avatar: '/imgs/workflow/userGuide.png',
avatar: 'core/workflow/template/systemConfig',
flowNodeType: 'userGuide',
position: {
x: 531.2422736065552,
@@ -1084,7 +1084,7 @@ export const workflowTemplates: TemplateType = [
nodeId: '448745',
name: '流程开始',
intro: '',
avatar: '/imgs/workflow/userChatInput.svg',
avatar: 'core/workflow/template/workflowStart',
flowNodeType: 'workflowStart',
position: {
x: 558.4082376415505,
@@ -1115,7 +1115,7 @@ export const workflowTemplates: TemplateType = [
nodeId: 'loOvhld2ZTKa',
name: '第一轮翻译',
intro: 'AI 大模型对话',
avatar: '/imgs/workflow/AI.png',
avatar: 'core/workflow/template/aiChat',
flowNodeType: 'chatNode',
showStatus: true,
position: {
@@ -1235,7 +1235,7 @@ export const workflowTemplates: TemplateType = [
nodeId: 'w0oBbQ3YJHye',
name: '代码运行',
intro: '执行一段简单的脚本代码,通常用于进行复杂的数据处理。',
avatar: '/imgs/workflow/code.svg',
avatar: 'core/workflow/template/codeRun',
flowNodeType: 'code',
showStatus: true,
position: {
@@ -1348,7 +1348,7 @@ export const workflowTemplates: TemplateType = [
name: '指定回复',
intro:
'该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。',
avatar: '/imgs/workflow/reply.png',
avatar: 'core/workflow/template/reply',
flowNodeType: 'answerNode',
position: {
x: 3798.4479531204515,
@@ -1374,7 +1374,7 @@ export const workflowTemplates: TemplateType = [
nodeId: 'gBDvemE4FBhp',
name: '文本拼接',
intro: '可对固定或传入的文本进行加工后输出,非字符串类型数据最终会转成字符串类型。',
avatar: '/imgs/workflow/textEditor.svg',
avatar: 'core/workflow/template/textConcat',
flowNodeType: 'textEditor',
position: {
x: 1031.371061396644,
@@ -1463,7 +1463,7 @@ export const workflowTemplates: TemplateType = [
nodeId: 'bcqtxqxE2R6o',
name: '合并输出结果',
intro: '可对固定或传入的文本进行加工后输出,非字符串类型数据最终会转成字符串类型。',
avatar: '/imgs/workflow/textEditor.svg',
avatar: 'core/workflow/template/textConcat',
flowNodeType: 'textEditor',
position: {
x: 3113.6227559936665,
@@ -1593,7 +1593,7 @@ export const workflowTemplates: TemplateType = [
nodeId: 'userGuide',
name: '系统配置',
intro: '可以配置应用的系统参数',
avatar: '/imgs/workflow/userGuide.png',
avatar: 'core/workflow/template/systemConfig',
flowNodeType: 'userGuide',
position: {
x: 262.2732338817093,
@@ -1656,7 +1656,7 @@ export const workflowTemplates: TemplateType = [
nodeId: '448745',
name: '流程开始',
intro: '',
avatar: '/imgs/workflow/userChatInput.svg',
avatar: 'core/workflow/template/workflowStart',
flowNodeType: 'workflowStart',
position: {
x: 295.8944548701009,
@@ -1687,7 +1687,7 @@ export const workflowTemplates: TemplateType = [
nodeId: 'NOgbnBzUwDgT',
name: '工具调用',
intro: '通过AI模型自动选择一个或多个功能块进行调用也可以对插件进行调用。',
avatar: '/imgs/workflow/tool.svg',
avatar: 'core/workflow/template/toolCall',
flowNodeType: 'tools',
showStatus: true,
position: {
@@ -1769,7 +1769,7 @@ export const workflowTemplates: TemplateType = [
nodeId: 'GMELVPxHfpg5',
name: 'HTTP 请求',
intro: '调用谷歌搜索,查询相关内容',
avatar: '/imgs/workflow/http.png',
avatar: 'core/workflow/template/httpRequest',
flowNodeType: 'httpRequest468',
showStatus: true,
position: {
@@ -1914,7 +1914,7 @@ export const workflowTemplates: TemplateType = [
nodeId: 'poIbrrA8aiR0',
name: '代码运行',
intro: '执行一段简单的脚本代码,通常用于进行复杂的数据处理。',
avatar: '/imgs/workflow/code.svg',
avatar: 'core/workflow/template/codeRun',
flowNodeType: 'code',
showStatus: true,
position: {
@@ -2032,7 +2032,7 @@ export const workflowTemplates: TemplateType = [
nodeId: 'userGuide',
name: '系统配置',
intro: '可以配置应用的系统参数',
avatar: '/imgs/workflow/userGuide.png',
avatar: 'core/workflow/template/systemConfig',
flowNodeType: 'userGuide',
position: {
x: 531.2422736065552,
@@ -2095,7 +2095,7 @@ export const workflowTemplates: TemplateType = [
nodeId: '448745',
name: '流程开始',
intro: '',
avatar: '/imgs/workflow/userChatInput.svg',
avatar: 'core/workflow/template/workflowStart',
flowNodeType: 'workflowStart',
position: {
x: 532.1275542407774,
@@ -2126,7 +2126,7 @@ export const workflowTemplates: TemplateType = [
nodeId: 'tMyUnRL5jIrC',
name: 'HTTP 请求',
intro: '可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)',
avatar: '/imgs/workflow/http.png',
avatar: 'core/workflow/template/httpRequest',
flowNodeType: 'httpRequest468',
showStatus: true,
position: {
@@ -2291,7 +2291,7 @@ export const workflowTemplates: TemplateType = [
name: '指定回复',
intro:
'该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。',
avatar: '/imgs/workflow/reply.png',
avatar: 'core/workflow/template/reply',
flowNodeType: 'answerNode',
position: {
x: 2204.4609372615846,
@@ -2317,7 +2317,7 @@ export const workflowTemplates: TemplateType = [
nodeId: 'vEXJF8pQ8eOv',
name: '文本拼接',
intro: '可对固定或传入的文本进行加工后输出,非字符串类型数据最终会转成字符串类型。',
avatar: '/imgs/workflow/textEditor.svg',
avatar: 'core/workflow/template/textConcat',
flowNodeType: 'textEditor',
position: {
x: 1544.8821308368042,
@@ -2426,7 +2426,7 @@ export const workflowTemplates: TemplateType = [
},
{
id: 'CQ',
avatar: '/imgs/workflow/cq.png',
avatar: 'core/workflow/template/questionClassify',
name: '问题分类 + 知识库',
intro: '先对用户的问题进行分类,再根据不同类型问题,执行不同的操作',
type: AppTypeEnum.workflow,
@@ -2435,7 +2435,7 @@ export const workflowTemplates: TemplateType = [
nodeId: 'userGuide',
name: '系统配置',
intro: '可以配置应用的系统参数',
avatar: '/imgs/workflow/userGuide.png',
avatar: 'core/workflow/template/systemConfig',
flowNodeType: FlowNodeTypeEnum.systemConfig,
position: {
x: 531.2422736065552,
@@ -2498,7 +2498,7 @@ export const workflowTemplates: TemplateType = [
nodeId: 'workflowStartNodeId',
name: '流程开始',
intro: '',
avatar: '/imgs/workflow/userChatInput.svg',
avatar: 'core/workflow/template/workflowStart',
flowNodeType: FlowNodeTypeEnum.workflowStart,
position: {
x: 558.4082376415505,
@@ -2529,7 +2529,7 @@ export const workflowTemplates: TemplateType = [
nodeId: '7BdojPlukIQw',
name: 'AI 对话',
intro: 'AI 大模型对话',
avatar: '/imgs/workflow/AI.png',
avatar: 'core/workflow/template/aiChat',
flowNodeType: FlowNodeTypeEnum.chatNode,
showStatus: true,
position: {
@@ -2546,7 +2546,7 @@ export const workflowTemplates: TemplateType = [
],
label: 'core.module.input.label.aiModel',
valueType: WorkflowIOValueTypeEnum.string,
value: 'gpt-3.5-turbo'
value: 'gpt-4o-mini'
},
{
key: 'temperature',
@@ -2650,7 +2650,7 @@ export const workflowTemplates: TemplateType = [
name: '问题分类',
intro:
'根据用户的历史记录和当前问题判断该次提问的类型。可以添加多组问题类型,下面是一个模板例子:\n类型1: 打招呼\n类型2: 关于商品“使用”问题\n类型3: 关于商品“购买”问题\n类型4: 其他问题',
avatar: '/imgs/workflow/cq.png',
avatar: 'core/workflow/template/questionClassify',
flowNodeType: FlowNodeTypeEnum.classifyQuestion,
showStatus: true,
position: {
@@ -2666,7 +2666,7 @@ export const workflowTemplates: TemplateType = [
required: true,
valueType: WorkflowIOValueTypeEnum.string,
llmModelType: 'classify',
value: 'gpt-3.5-turbo'
value: 'gpt-4o-mini'
},
{
key: 'systemPrompt',
@@ -2732,7 +2732,7 @@ export const workflowTemplates: TemplateType = [
name: '指定回复',
intro:
'该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。',
avatar: '/imgs/workflow/reply.png',
avatar: 'core/workflow/template/reply',
flowNodeType: FlowNodeTypeEnum.answerNode,
position: {
x: 1874.9167551056487,
@@ -2757,7 +2757,7 @@ export const workflowTemplates: TemplateType = [
nodeId: 'MNMMMIjjWyMU',
name: '知识库搜索',
intro: '调用“语义检索”和“全文检索”能力,从“知识库”中查找可能与问题相关的参考内容',
avatar: '/imgs/workflow/db.png',
avatar: 'core/workflow/template/datasetSearch',
flowNodeType: FlowNodeTypeEnum.datasetSearchNode,
showStatus: true,
position: {
@@ -2883,7 +2883,7 @@ export const workflowTemplates: TemplateType = [
export const pluginTemplates: TemplateType = [
{
id: 'plugin-simple',
avatar: '/imgs/workflow/AI.png',
avatar: 'core/workflow/template/aiChat',
name: '默认模板',
intro: '标准的插件初始模板',
type: AppTypeEnum.plugin,
@@ -2891,7 +2891,7 @@ export const pluginTemplates: TemplateType = [
{
nodeId: 'pluginInput',
name: '自定义插件输入',
avatar: '/imgs/workflow/input.png',
avatar: 'core/workflow/template/workflowStart',
flowNodeType: FlowNodeTypeEnum.pluginInput,
showStatus: false,
position: {
@@ -2930,7 +2930,7 @@ export const pluginTemplates: TemplateType = [
nodeId: 'pluginInput',
name: '自定义插件输入',
intro: '自定义配置外部输入,使用插件时,仅暴露自定义配置的输入',
avatar: '/imgs/workflow/input.png',
avatar: 'core/workflow/template/workflowStart',
flowNodeType: 'pluginInput',
showStatus: false,
position: {
@@ -3015,7 +3015,7 @@ export const pluginTemplates: TemplateType = [
nodeId: 'rKBYGQuYefae',
name: 'HTTP 请求',
intro: '可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)',
avatar: '/imgs/workflow/http.png',
avatar: 'core/workflow/template/httpRequest',
flowNodeType: 'httpRequest468',
showStatus: true,
position: {

View File

@@ -84,6 +84,7 @@ export const storeNode2FlowNode = ({
const nodeItem: FlowNodeItemType = {
...template,
...storeNode,
avatar: template.avatar ?? storeNode.avatar,
version: storeNode.version ?? template.version ?? defaultNodeVersion,
/*