4.8.8 test fix (#2149)

* perf: code comment

* feat: system plugin input guide

* perf: variable avatar

* feat: feishu webhook

* perf: select tool config tip

* perf: rename variable

* fix: per inherit error

* perf: docker-compose oneapi version and i18n

* perf: ui tip bug

* fix: ts

* perf: pg log

* perf: editor color

* perf: update init
This commit is contained in:
Archer
2024-07-26 10:23:44 +08:00
committed by GitHub
parent 2d016b7462
commit cd554f573e
59 changed files with 1648 additions and 506 deletions

View File

@@ -0,0 +1,46 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { jsonRes } from '@fastgpt/service/common/response';
import { connectToDatabase } from '@/service/mongo';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { MongoDataset } from '@fastgpt/service/core/dataset/schema';
import { DatasetDefaultPermissionVal } from '@fastgpt/global/support/permission/dataset/constant';
/* pg 中的数据搬到 mongo dataset.datas 中,并做映射 */
export default async function handler(req: NextApiRequest, res: NextApiResponse) {
try {
await connectToDatabase();
await authCert({ req, authRoot: true });
await MongoDataset.updateMany(
{
inheritPermission: { $exists: false }
},
{
$set: {
inheritPermission: true
}
}
);
await MongoDataset.updateMany(
{
defaultPermission: { $exists: false }
},
{
$set: {
defaultPermission: DatasetDefaultPermissionVal
}
}
);
jsonRes(res, {
message: 'success'
});
} catch (error) {
console.log(error);
jsonRes(res, {
code: 500,
error
});
}
}

View File

@@ -89,7 +89,7 @@ async function handler(req: ApiRequestProps<AppUpdateParams, { appId: string }>)
defaultPermission: updatedDefaultPermission
}),
// Not root, update default permission
...(isDefaultPermissionChanged && { inheritPermission: false }),
...(app.parentId && isDefaultPermissionChanged && { inheritPermission: false }),
...(teamTags && { teamTags }),
...(formatNodes && {
modules: formatNodes

View File

@@ -15,7 +15,7 @@ import { removeEmptyUserInput } from '@fastgpt/global/core/chat/utils';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import {
filterPluginInputVariables,
removePluginInputVariables,
updatePluginInputByVariables
} from '@fastgpt/global/core/workflow/utils';
import { NextAPI } from '@/service/middleware/entry';
@@ -66,7 +66,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
// Plugin need to replace inputs
if (isPlugin) {
nodes = updatePluginInputByVariables(nodes, variables);
variables = filterPluginInputVariables(variables, nodes);
variables = removePluginInputVariables(variables, nodes);
} else {
if (!userInput) {
throw new Error('Params Error');

View File

@@ -24,7 +24,7 @@ async function handler(req: NextApiRequest) {
searchMode,
usingReRank,
datasetSearchUsingExtensionQuery = false,
datasetSearchUsingExtensionQuery = true,
datasetSearchExtensionModel,
datasetSearchExtensionBg = ''
} = req.body as SearchTestProps;

View File

@@ -78,7 +78,7 @@ async function handler(
defaultPermission: updatedDefaultPermission
}),
// update the defaultPermission
...(isDefaultPermissionChanged && { inheritPermission: false })
...(dataset.parentId && isDefaultPermissionChanged && { inheritPermission: false })
},
{ session }
);

View File

@@ -55,7 +55,7 @@ import { getAppLatestVersion } from '@fastgpt/service/core/app/controller';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import {
filterPluginInputVariables,
removePluginInputVariables,
updatePluginInputByVariables
} from '@fastgpt/global/core/workflow/utils';
import { getNanoid } from '@fastgpt/global/common/string/tools';
@@ -238,7 +238,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
)
: storeNodes2RuntimeNodes(nodes, getDefaultEntryNodeIds(nodes));
const runtimeVariables = filterPluginInputVariables(
const runtimeVariables = removePluginInputVariables(
variables,
storeNodes2RuntimeNodes(nodes, getDefaultEntryNodeIds(nodes))
);

View File

@@ -113,8 +113,8 @@ const EditForm = ({
...item,
parent: {
id: 'VARIABLE_NODE_ID',
label: '全局变量',
avatar: '/imgs/workflow/variable.png'
label: t('common:core.module.Variable'),
avatar: 'core/workflow/template/variable'
}
})),
[appForm.chatConfig.variables, t]
@@ -230,6 +230,7 @@ const EditForm = ({
similarity={appForm.dataset.similarity}
limit={appForm.dataset.limit}
usingReRank={appForm.dataset.usingReRank}
datasetSearchUsingExtensionQuery={appForm.dataset.datasetSearchUsingExtensionQuery}
queryExtensionModel={appForm.dataset.datasetSearchExtensionModel}
/>
</Box>

View File

@@ -92,7 +92,12 @@ const Header = ({
)}
<Flex pt={[2, 3]} alignItems={'flex-start'} position={'relative'}>
<Box flex={'1'}>
<FolderPath paths={paths} hoverStyle={{ color: 'primary.600' }} onClick={onclickRoute} />
<FolderPath
rootName={t('app:all_apps')}
paths={paths}
hoverStyle={{ color: 'primary.600' }}
onClick={onclickRoute}
/>
</Box>
{isPc && (
<Box position={'absolute'} left={'50%'} transform={'translateX(-50%)'}>

View File

@@ -6,6 +6,7 @@ import {
Box,
Button,
Flex,
HStack,
Input,
InputGroup,
InputLeftElement,
@@ -287,6 +288,8 @@ const RenderList = React.memo(function RenderList({
</MyTooltip>
);
})}
{/* Plugin input config */}
{!!configTool && (
<MyModal
isOpen
@@ -295,6 +298,19 @@ const RenderList = React.memo(function RenderList({
overflow={'auto'}
>
<ModalBody>
<HStack mb={4} spacing={1} fontSize={'sm'}>
<MyIcon name={'common/info'} w={'1.25rem'} />
<Box flex={1}>{t('app:tool_input_param_tip')}</Box>
{configTool.inputExplanationUrl && (
<Box
cursor={'pointer'}
color={'primary.500'}
onClick={() => window.open(configTool.inputExplanationUrl, '_blank')}
>
{t('app:workflow.Input guide')}
</Box>
)}
</HStack>
{configTool.inputs
.filter((item) => !item.toolDescription)
.map((input) => {

View File

@@ -334,7 +334,7 @@ const RenderList = React.memo(function RenderList({
const { computedNewNodeName } = useWorkflowUtils();
const formatTemplates = useMemo<NodeTemplateListType>(() => {
const copy: NodeTemplateListType = cloneDeep(workflowNodeTemplateList(t));
const copy: NodeTemplateListType = cloneDeep(workflowNodeTemplateList);
templates.forEach((item) => {
const index = copy.findIndex((template) => template.type === item.templateType);
if (index === -1) return;

View File

@@ -1,12 +1,30 @@
import React from 'react';
import { Box, Flex, FlexProps } from '@chakra-ui/react';
import { Box, StackProps, HStack } from '@chakra-ui/react';
import { useTranslation } from 'next-i18next';
const IOTitle = ({
text,
inputExplanationUrl,
...props
}: { text?: 'Input' | 'Output' | string; inputExplanationUrl?: string } & StackProps) => {
const { t } = useTranslation();
const IOTitle = ({ text, ...props }: { text?: 'Input' | 'Output' | string } & FlexProps) => {
return (
<Flex fontSize={'md'} alignItems={'center'} fontWeight={'medium'} mb={3} {...props}>
<Box w={'3px'} h={'14px'} borderRadius={'13px'} bg={'primary.600'} mr={1.5} />
{text}
</Flex>
<HStack fontSize={'md'} alignItems={'center'} fontWeight={'medium'} mb={3} {...props}>
<Box w={'3px'} h={'14px'} borderRadius={'13px'} bg={'primary.600'} />
<Box>{text}</Box>
<Box flex={1} />
{inputExplanationUrl && (
<Box
cursor={'pointer'}
color={'primary.500'}
onClick={() => window.open(inputExplanationUrl, '_blank')}
>
{t('app:workflow.Input guide')}
</Box>
)}
</HStack>
);
};

View File

@@ -37,7 +37,10 @@ const NodeSimple = ({
{filterHiddenInputs.length > 0 && (
<>
<Container>
<IOTitle text={t('common:common.Input')} />
<IOTitle
text={t('common:common.Input')}
inputExplanationUrl={data.inputExplanationUrl}
/>
<RenderInput nodeId={nodeId} flowInputList={commonInputs} />
</Container>
</>

View File

@@ -80,27 +80,36 @@ const NodeCard = (props: Props) => {
const node = nodeList.find((node) => node.nodeId === nodeId);
const { openConfirm: onOpenConfirmSync, ConfirmModal: ConfirmSyncModal } = useConfirm({
content: appT('module.Confirm Sync')
content: t('app:module.Confirm Sync')
});
const { data: newNodeVersion, runAsync: getNodeVersion } = useRequest2(
const { data: nodeTemplate, runAsync: getNodeLatestTemplate } = useRequest2(
async () => {
if (node?.flowNodeType === FlowNodeTypeEnum.pluginModule) {
if (!node?.pluginId) return;
const template = await getPreviewPluginNode({ appId: node.pluginId });
return template.version;
// Focus update plugin latest inputExplanationUrl
onChangeNode({
nodeId,
type: 'attr',
key: 'inputExplanationUrl',
value: template.inputExplanationUrl
});
return template;
} else {
const template = moduleTemplatesFlat.find(
(item) => item.flowNodeType === node?.flowNodeType
);
return template?.version;
return template;
}
},
{
manual: false
}
);
const hasNewVersion = newNodeVersion && newNodeVersion !== node?.version;
const hasNewVersion = nodeTemplate && nodeTemplate.version !== node?.version;
const { runAsync: onClickSyncVersion } = useRequest2(
async () => {
@@ -119,10 +128,10 @@ const NodeCard = (props: Props) => {
node: getLatestNodeTemplate(node, template)
});
}
await getNodeVersion();
await getNodeLatestTemplate();
},
{
refreshDeps: [node, nodeId, onResetNode, getNodeVersion]
refreshDeps: [node, nodeId, onResetNode, getNodeLatestTemplate]
}
);

View File

@@ -1,6 +1,6 @@
import React, { useEffect, useMemo, useState } from 'react';
import type { RenderInputProps } from '../type';
import { Box, Button, Flex, useDisclosure } from '@chakra-ui/react';
import { Flex, useDisclosure } from '@chakra-ui/react';
import { useTranslation } from 'next-i18next';
import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constants';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
@@ -54,7 +54,8 @@ const SelectDatasetParam = ({ inputs = [], nodeId }: RenderInputProps) => {
if (data[input.key] !== undefined) {
setData((state) => ({
...state,
[input.key]: input.value
// @ts-ignore
[input.key]: input.value || state[input.key]
}));
}
});
@@ -82,6 +83,7 @@ const SelectDatasetParam = ({ inputs = [], nodeId }: RenderInputProps) => {
similarity={data.similarity}
limit={data.limit}
usingReRank={data.usingReRank}
datasetSearchUsingExtensionQuery={data.datasetSearchUsingExtensionQuery}
queryExtensionModel={data.datasetSearchExtensionModel}
/>
</>

View File

@@ -10,7 +10,7 @@ const TextInput = ({ item, nodeId }: RenderInputProps) => {
const Render = useMemo(() => {
return (
<Input
placeholder={item.placeholder}
placeholder={item.placeholder ?? item.description}
defaultValue={item.value}
bg={'white'}
px={3}

View File

@@ -14,7 +14,6 @@ import { AppUpdateParams } from '@/global/core/app/api';
import dynamic from 'next/dynamic';
import { useI18n } from '@/web/context/I18n';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { useThrottleEffect } from 'ahooks';
const MoveModal = dynamic(() => import('@/components/common/folder/MoveModal'));
type AppListContextType = {

View File

@@ -131,10 +131,10 @@ const MobileDrawer = ({
}}
list={[
...(isTeamChat
? [{ label: t('common:all_apps'), value: TabEnum.recently }]
? [{ label: t('app:all_apps'), value: TabEnum.recently }]
: [
{ label: t('common:core.chat.Recent use'), value: TabEnum.recently },
{ label: t('common:all_apps'), value: TabEnum.app }
{ label: t('app:all_apps'), value: TabEnum.app }
])
]}
value={currentTab}

View File

@@ -71,7 +71,7 @@ const Test = ({ datasetId }: { datasetId: string }) => {
usingReRank: false,
limit: 5000,
similarity: 0,
datasetSearchUsingExtensionQuery: false,
datasetSearchUsingExtensionQuery: true,
datasetSearchExtensionModel: llmModelList[0].model,
datasetSearchExtensionBg: ''
}
@@ -432,6 +432,7 @@ const TestResults = React.memo(function TestResults({
similarity={datasetTestItem.similarity}
limit={datasetTestItem.limit}
usingReRank={datasetTestItem.usingReRank}
datasetSearchUsingExtensionQuery={!!datasetTestItem.queryExtensionModel}
queryExtensionModel={datasetTestItem.queryExtensionModel}
/>
</Box>

View File

@@ -68,7 +68,11 @@ function DatasetContextProvider({ children }: { children: React.ReactNode }) {
const { parentId = null } = router.query as { parentId?: string | null };
const { data: myDatasets = [], runAsync: loadMyDatasets } = useRequest2(
const {
data: myDatasets = [],
runAsync: loadMyDatasets,
loading: isFetchingDatasets
} = useRequest2(
() =>
getDatasets({
parentId
@@ -83,7 +87,7 @@ function DatasetContextProvider({ children }: { children: React.ReactNode }) {
() => (parentId ? getDatasetById(parentId) : Promise.resolve(undefined)),
{
manual: false,
refreshDeps: [parentId, myDatasets]
refreshDeps: [parentId]
}
);
@@ -95,16 +99,8 @@ function DatasetContextProvider({ children }: { children: React.ReactNode }) {
}
);
const { runAsync: refetchDatasets, loading: isFetchingDatasets } = useRequest2(
() => loadMyDatasets(),
{
manual: false,
refreshDeps: [parentId]
}
);
const { runAsync: onUpdateDataset } = useRequest2(putDatasetById, {
onSuccess: () => Promise.all([refetchDatasets(), refetchPaths(), loadMyDatasets()])
onSuccess: () => Promise.all([refetchFolderDetail(), refetchPaths(), loadMyDatasets()])
});
const onMoveDataset = useCallback(
@@ -138,7 +134,6 @@ function DatasetContextProvider({ children }: { children: React.ReactNode }) {
});
const contextValue = {
refetchDatasets,
isFetchingDatasets,
setMoveDatasetId,
paths,