feat: node version (#1484)

* feat: node version tip

* fix

* i18n

* init version

* fix ts

* fix ts

* fix ts
This commit is contained in:
heheer
2024-05-14 23:26:03 +08:00
committed by GitHub
parent b779e2806d
commit fb04889a31
37 changed files with 185 additions and 20 deletions

View File

@@ -131,6 +131,7 @@ export const appWorkflow2Form = ({ nodes }: { nodes: StoreNodeItemType[] }) => {
intro: node.intro || '', intro: node.intro || '',
flowNodeType: node.flowNodeType, flowNodeType: node.flowNodeType,
showStatus: node.showStatus, showStatus: node.showStatus,
version: '481',
inputs: node.inputs, inputs: node.inputs,
outputs: node.outputs, outputs: node.outputs,
templateType: FlowNodeTemplateTypeEnum.other templateType: FlowNodeTemplateTypeEnum.other

View File

@@ -282,6 +282,7 @@ export const httpApiSchema2Plugins = async ({
x: 616.4226348688949, x: 616.4226348688949,
y: -165.05298493910115 y: -165.05298493910115
}, },
version: PluginInputModule.version,
inputs: pluginInputs, inputs: pluginInputs,
outputs: pluginOutputs outputs: pluginOutputs
}, },
@@ -296,6 +297,7 @@ export const httpApiSchema2Plugins = async ({
x: 1607.7142331269126, x: 1607.7142331269126,
y: -151.8669210746189 y: -151.8669210746189
}, },
version: PluginOutputModule.version,
inputs: [ inputs: [
{ {
key: pluginOutputKey, key: pluginOutputKey,
@@ -334,6 +336,7 @@ export const httpApiSchema2Plugins = async ({
x: 1042.549746602742, x: 1042.549746602742,
y: -447.77496332641647 y: -447.77496332641647
}, },
version: HttpModule468.version,
inputs: [ inputs: [
{ {
key: NodeInputKeyEnum.addInputParam, key: NodeInputKeyEnum.addInputParam,

View File

@@ -31,6 +31,7 @@ export const AiChatModule: FlowNodeTemplateType = {
intro: 'AI 大模型对话', intro: 'AI 大模型对话',
showStatus: true, showStatus: true,
isTool: true, isTool: true,
version: '481',
inputs: [ inputs: [
Input_Template_SettingAiModel, Input_Template_SettingAiModel,
// --- settings modal // --- settings modal

View File

@@ -17,6 +17,7 @@ export const AssignedAnswerModule: FlowNodeTemplateType = {
name: '指定回复', name: '指定回复',
intro: intro:
'该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。', '该模块可以直接回复一段指定的内容。常用于引导、提示。非字符串内容传入时,会转成字符串进行输出。',
version: '481',
inputs: [ inputs: [
{ {
key: NodeInputKeyEnum.answerText, key: NodeInputKeyEnum.answerText,

View File

@@ -29,6 +29,7 @@ export const ClassifyQuestionModule: FlowNodeTemplateType = {
name: '问题分类', name: '问题分类',
intro: `根据用户的历史记录和当前问题判断该次提问的类型。可以添加多组问题类型,下面是一个模板例子:\n类型1: 打招呼\n类型2: 关于商品“使用”问题\n类型3: 关于商品“购买”问题\n类型4: 其他问题`, intro: `根据用户的历史记录和当前问题判断该次提问的类型。可以添加多组问题类型,下面是一个模板例子:\n类型1: 打招呼\n类型2: 关于商品“使用”问题\n类型3: 关于商品“购买”问题\n类型4: 其他问题`,
showStatus: true, showStatus: true,
version: '481',
inputs: [ inputs: [
{ {
...Input_Template_SelectAIModel, ...Input_Template_SelectAIModel,

View File

@@ -25,6 +25,7 @@ export const ContextExtractModule: FlowNodeTemplateType = {
intro: '可从文本中提取指定的数据例如sql语句、搜索关键词、代码等', intro: '可从文本中提取指定的数据例如sql语句、搜索关键词、代码等',
showStatus: true, showStatus: true,
isTool: true, isTool: true,
version: '481',
inputs: [ inputs: [
{ {
...Input_Template_SelectAIModel, ...Input_Template_SelectAIModel,

View File

@@ -42,6 +42,7 @@ export const DatasetConcatModule: FlowNodeTemplateType = {
name: '知识库搜索引用合并', name: '知识库搜索引用合并',
intro: '可以将多个知识库搜索结果进行合并输出。使用 RRF 的合并方式进行最终排序输出。', intro: '可以将多个知识库搜索结果进行合并输出。使用 RRF 的合并方式进行最终排序输出。',
showStatus: false, showStatus: false,
version: '481',
inputs: [ inputs: [
{ {
key: NodeInputKeyEnum.datasetMaxTokens, key: NodeInputKeyEnum.datasetMaxTokens,

View File

@@ -28,6 +28,7 @@ export const DatasetSearchModule: FlowNodeTemplateType = {
intro: Dataset_SEARCH_DESC, intro: Dataset_SEARCH_DESC,
showStatus: true, showStatus: true,
isTool: true, isTool: true,
version: '481',
inputs: [ inputs: [
{ {
key: NodeInputKeyEnum.datasetSelectList, key: NodeInputKeyEnum.datasetSelectList,

View File

@@ -12,6 +12,7 @@ export const EmptyNode: FlowNodeTemplateType = {
avatar: '', avatar: '',
name: '', name: '',
intro: '', intro: '',
version: '481',
inputs: [], inputs: [],
outputs: [] outputs: []
}; };

View File

@@ -20,6 +20,7 @@ export const getGlobalVariableNode = ({
avatar: '/imgs/workflow/variable.png', avatar: '/imgs/workflow/variable.png',
name: '全局变量', name: '全局变量',
intro: '', intro: '',
version: '481',
inputs: [], inputs: [],
outputs: variables.map((item) => ({ outputs: variables.map((item) => ({
id: item.key, id: item.key,

View File

@@ -25,6 +25,7 @@ export const HttpModule468: FlowNodeTemplateType = {
intro: '可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)', intro: '可以发出一个 HTTP 请求,实现更为复杂的操作(联网搜索、数据库查询等)',
showStatus: true, showStatus: true,
isTool: true, isTool: true,
version: '481',
inputs: [ inputs: [
{ {
...Input_Template_DynamicInput, ...Input_Template_DynamicInput,

View File

@@ -22,6 +22,7 @@ export const IfElseNode: FlowNodeTemplateType = {
name: '判断器', name: '判断器',
intro: '根据一定的条件,执行不同的分支。', intro: '根据一定的条件,执行不同的分支。',
showStatus: true, showStatus: true,
version: '481',
inputs: [ inputs: [
{ {
key: NodeInputKeyEnum.ifElseList, key: NodeInputKeyEnum.ifElseList,

View File

@@ -25,6 +25,7 @@ export const LafModule: FlowNodeTemplateType = {
intro: '可以调用Laf账号下的云函数。', intro: '可以调用Laf账号下的云函数。',
showStatus: true, showStatus: true,
isTool: true, isTool: true,
version: '481',
inputs: [ inputs: [
{ {
...Input_Template_DynamicInput, ...Input_Template_DynamicInput,

View File

@@ -15,6 +15,7 @@ export const PluginInputModule: FlowNodeTemplateType = {
name: '自定义插件输入', name: '自定义插件输入',
intro: '自定义配置外部输入,使用插件时,仅暴露自定义配置的输入', intro: '自定义配置外部输入,使用插件时,仅暴露自定义配置的输入',
showStatus: false, showStatus: false,
version: '481',
inputs: [], inputs: [],
outputs: [] outputs: []
}; };

View File

@@ -15,6 +15,7 @@ export const PluginOutputModule: FlowNodeTemplateType = {
name: '自定义插件输出', name: '自定义插件输出',
intro: '自定义配置外部输出,使用插件时,仅暴露自定义配置的输出', intro: '自定义配置外部输出,使用插件时,仅暴露自定义配置的输出',
showStatus: false, showStatus: false,
version: '481',
inputs: [], inputs: [],
outputs: [] outputs: []
}; };

View File

@@ -29,6 +29,7 @@ export const AiQueryExtension: FlowNodeTemplateType = {
intro: intro:
'使用问题优化功能,可以提高知识库连续对话时搜索的精度。使用该功能后,会先利用 AI 根据上下文构建一个或多个新的检索词,这些检索词更利于进行知识库搜索。该模块已内置在知识库搜索模块中,如果您仅进行一次知识库搜索,可直接使用知识库内置的补全功能。', '使用问题优化功能,可以提高知识库连续对话时搜索的精度。使用该功能后,会先利用 AI 根据上下文构建一个或多个新的检索词,这些检索词更利于进行知识库搜索。该模块已内置在知识库搜索模块中,如果您仅进行一次知识库搜索,可直接使用知识库内置的补全功能。',
showStatus: true, showStatus: true,
version: '481',
inputs: [ inputs: [
{ {
...Input_Template_SelectAIModel, ...Input_Template_SelectAIModel,

View File

@@ -23,6 +23,7 @@ export const RunAppModule: FlowNodeTemplateType = {
name: '应用调用', name: '应用调用',
intro: '可以选择一个其他应用进行调用', intro: '可以选择一个其他应用进行调用',
showStatus: true, showStatus: true,
version: '481',
inputs: [ inputs: [
{ {
key: NodeInputKeyEnum.runAppSelectApp, key: NodeInputKeyEnum.runAppSelectApp,

View File

@@ -13,6 +13,7 @@ export const RunPluginModule: FlowNodeTemplateType = {
name: '', name: '',
showStatus: false, showStatus: false,
isTool: true, isTool: true,
version: '481',
inputs: [], // [{key:'pluginId'},...] inputs: [], // [{key:'pluginId'},...]
outputs: [] outputs: []
}; };

View File

@@ -13,6 +13,7 @@ export const StopToolNode: FlowNodeTemplateType = {
name: '工具调用终止', name: '工具调用终止',
intro: intro:
'该模块需配置工具调用使用。当该模块被执行时本次工具调用将会强制结束并且不再调用AI针对工具调用结果回答问题。', '该模块需配置工具调用使用。当该模块被执行时本次工具调用将会强制结束并且不再调用AI针对工具调用结果回答问题。',
version: '481',
inputs: [], inputs: [],
outputs: [] outputs: []
}; };

View File

@@ -18,6 +18,7 @@ export const SystemConfigNode: FlowNodeTemplateType = {
intro: '可以配置应用的系统参数。', intro: '可以配置应用的系统参数。',
unique: true, unique: true,
forbidDelete: true, forbidDelete: true,
version: '481',
inputs: [ inputs: [
{ {
key: NodeInputKeyEnum.welcomeText, key: NodeInputKeyEnum.welcomeText,

View File

@@ -30,6 +30,7 @@ export const ToolModule: FlowNodeTemplateType = {
name: '工具调用(实验)', name: '工具调用(实验)',
intro: '通过AI模型自动选择一个或多个功能块进行调用也可以对插件进行调用。', intro: '通过AI模型自动选择一个或多个功能块进行调用也可以对插件进行调用。',
showStatus: true, showStatus: true,
version: '481',
inputs: [ inputs: [
{ {
...Input_Template_SettingAiModel, ...Input_Template_SettingAiModel,

View File

@@ -18,6 +18,7 @@ export const VariableUpdateNode: FlowNodeTemplateType = {
intro: '可以更新指定节点的输出值或更新全局变量', intro: '可以更新指定节点的输出值或更新全局变量',
showStatus: true, showStatus: true,
isTool: false, isTool: false,
version: '481',
inputs: [ inputs: [
{ {
key: NodeInputKeyEnum.updateList, key: NodeInputKeyEnum.updateList,

View File

@@ -19,6 +19,7 @@ export const WorkflowStart: FlowNodeTemplateType = {
intro: '', intro: '',
forbidDelete: true, forbidDelete: true,
unique: true, unique: true,
version: '481',
inputs: [{ ...Input_Template_UserChatInput, toolDescription: '用户问题' }], inputs: [{ ...Input_Template_UserChatInput, toolDescription: '用户问题' }],
outputs: [ outputs: [
{ {

View File

@@ -28,6 +28,7 @@ export type FlowNodeCommonType = {
name: string; name: string;
intro?: string; // template list intro intro?: string; // template list intro
showStatus?: boolean; // chatting response step status showStatus?: boolean; // chatting response step status
version: string;
// data // data
inputs: FlowNodeInputItemType[]; inputs: FlowNodeInputItemType[];

View File

@@ -72,6 +72,7 @@ export async function getPluginPreviewNode({ id }: { id: string }): Promise<Flow
intro: plugin.intro, intro: plugin.intro,
showStatus: plugin.showStatus, showStatus: plugin.showStatus,
isTool: plugin.isTool, isTool: plugin.isTool,
version: '481',
sourceHandle: getHandleConfig(true, true, true, true), sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true), targetHandle: getHandleConfig(true, true, true, true),
...pluginData2FlowNodeIO(plugin.nodes) ...pluginData2FlowNodeIO(plugin.nodes)

View File

@@ -521,6 +521,19 @@ export const theme = extendTheme({
800: '#05603A', 800: '#05603A',
900: '#054F31' 900: '#054F31'
}, },
yellow: {
25: '#FFFDFA',
50: '#FFFAEB',
100: '#FEF0C7',
200: '#FEDF89',
300: '#F5C149',
400: '#FDB022',
500: '#F79009',
600: '#DC6803',
700: '#B54708',
800: '#93370D',
900: '#7A2E0E'
},
borderColor: { borderColor: {
low: '#E8EBF0', low: '#E8EBF0',
base: '#DFE2EA', base: '#DFE2EA',

View File

@@ -31,6 +31,12 @@
"To Chat": "Go to Chat", "To Chat": "Go to Chat",
"To Settings": "View Details", "To Settings": "View Details",
"Variable Key Repeat Tip": "Variable key is duplicate", "Variable Key Repeat Tip": "Variable key is duplicate",
"app": {
"modules": {
"click to update": "click to update",
"has new version": "has new version"
}
},
"module": { "module": {
"Combine Modules": "Combine Modules", "Combine Modules": "Combine Modules",
"Custom Title Tip": "This title will be displayed during the conversation", "Custom Title Tip": "This title will be displayed during the conversation",

View File

@@ -30,6 +30,12 @@
"To Chat": "前去对话", "To Chat": "前去对话",
"To Settings": "查看详情", "To Settings": "查看详情",
"Variable Key Repeat Tip": "变量 key 重复", "Variable Key Repeat Tip": "变量 key 重复",
"app": {
"modules": {
"click to update": "点击更新",
"has new version": "有新版本"
}
},
"module": { "module": {
"Combine Modules": "组合模块", "Combine Modules": "组合模块",
"Custom Title Tip": "该标题名字会展示在对话过程中", "Custom Title Tip": "该标题名字会展示在对话过程中",

View File

@@ -18,11 +18,14 @@ import { ResponseBox } from '@/components/ChatBox/WholeResponseModal';
import EmptyTip from '@fastgpt/web/components/common/EmptyTip'; import EmptyTip from '@fastgpt/web/components/common/EmptyTip';
import { getPreviewPluginModule } from '@/web/core/plugin/api'; import { getPreviewPluginModule } from '@/web/core/plugin/api';
import { getErrText } from '@fastgpt/global/common/error/utils'; import { getErrText } from '@fastgpt/global/common/error/utils';
import { storeNode2FlowNode } from '@/web/core/workflow/utils'; import { storeNode2FlowNode, updateFlowNodeVersion } from '@/web/core/workflow/utils';
import { getNanoid } from '@fastgpt/global/common/string/tools'; import { getNanoid } from '@fastgpt/global/common/string/tools';
import { useContextSelector } from 'use-context-selector'; import { useContextSelector } from 'use-context-selector';
import { WorkflowContext } from '../../../context'; import { WorkflowContext } from '../../../context';
import { useI18n } from '@/web/context/I18n'; import { useI18n } from '@/web/context/I18n';
import { moduleTemplatesFlat } from '@fastgpt/global/core/workflow/template/constants';
import { QuestionOutlineIcon } from '@chakra-ui/icons';
import MyTooltip from '@/components/MyTooltip';
type Props = FlowNodeItemType & { type Props = FlowNodeItemType & {
children?: React.ReactNode | React.ReactNode[] | string; children?: React.ReactNode | React.ReactNode[] | string;
@@ -65,6 +68,7 @@ const NodeCard = (props: Props) => {
const setHoverNodeId = useContextSelector(WorkflowContext, (v) => v.setHoverNodeId); const setHoverNodeId = useContextSelector(WorkflowContext, (v) => v.setHoverNodeId);
const onUpdateNodeError = useContextSelector(WorkflowContext, (v) => v.onUpdateNodeError); const onUpdateNodeError = useContextSelector(WorkflowContext, (v) => v.onUpdateNodeError);
const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode); const onChangeNode = useContextSelector(WorkflowContext, (v) => v.onChangeNode);
const onResetNode = useContextSelector(WorkflowContext, (v) => v.onResetNode);
// custom title edit // custom title edit
const { onOpenModal: onOpenCustomTitleModal, EditModal: EditTitleModal } = useEditTitle({ const { onOpenModal: onOpenCustomTitleModal, EditModal: EditTitleModal } = useEditTitle({
@@ -77,12 +81,21 @@ const NodeCard = (props: Props) => {
[isTool, nodeList] [isTool, nodeList]
); );
const node = nodeList.find((node) => node.nodeId === nodeId);
const template = moduleTemplatesFlat.find((item) => item.flowNodeType === node?.flowNodeType);
const hasNewVersion = useMemo(() => {
return (
template?.flowNodeType !== FlowNodeTypeEnum.pluginModule &&
node?.version !== template?.version
);
}, [node?.version, template?.flowNodeType, template?.version]);
/* Node header */ /* Node header */
const Header = useMemo(() => { const Header = useMemo(() => {
return ( return (
<Box position={'relative'}> <Box position={'relative'}>
{/* debug */} {/* debug */}
<Box className="custom-drag-handle" px={4} py={3}> <Box px={4} py={3}>
{/* tool target handle */} {/* tool target handle */}
{showToolHandle && <ToolTargetHandle nodeId={nodeId} />} {showToolHandle && <ToolTargetHandle nodeId={nodeId} />}
@@ -123,6 +136,33 @@ const NodeCard = (props: Props) => {
}} }}
/> />
)} )}
<Box flex={1} />
{hasNewVersion && (
<MyTooltip label={appT('app.modules.click to update')}>
<Button
bg={'yellow.50'}
color={'yellow.600'}
variant={'ghost'}
h={8}
px={2}
rounded={'6px'}
fontSize={'xs'}
fontWeight={'medium'}
cursor={'pointer'}
_hover={{ bg: 'yellow.100' }}
onClick={() => {
if (!node || !template) return;
onResetNode({
id: nodeId,
node: updateFlowNodeVersion(node, template)
});
}}
>
<Box>{appT('app.modules.has new version')}</Box>
<QuestionOutlineIcon ml={1} />
</Button>
</MyTooltip>
)}
</Flex> </Flex>
<MenuRender <MenuRender
nodeId={nodeId} nodeId={nodeId}
@@ -141,13 +181,17 @@ const NodeCard = (props: Props) => {
t, t,
name, name,
menuForbid, menuForbid,
hasNewVersion,
pluginId, pluginId,
flowNodeType, flowNodeType,
intro, intro,
onOpenCustomTitleModal, onOpenCustomTitleModal,
onChangeNode, onChangeNode,
toast, toast,
appT appT,
node,
template,
onResetNode
]); ]);
return ( return (
@@ -236,7 +280,8 @@ const MenuRender = React.memo(function MenuRender({
inputs: node.data.inputs, inputs: node.data.inputs,
outputs: node.data.outputs, outputs: node.data.outputs,
showStatus: node.data.showStatus, showStatus: node.data.showStatus,
pluginId: node.data.pluginId pluginId: node.data.pluginId,
version: node.data.version
}; };
return state.concat( return state.concat(
storeNode2FlowNode({ storeNode2FlowNode({
@@ -250,7 +295,8 @@ const MenuRender = React.memo(function MenuRender({
showStatus: template.showStatus, showStatus: template.showStatus,
pluginId: template.pluginId, pluginId: template.pluginId,
inputs: template.inputs, inputs: template.inputs,
outputs: template.outputs outputs: template.outputs,
version: template.version
} }
}) })
); );
@@ -265,7 +311,7 @@ const MenuRender = React.memo(function MenuRender({
}, },
[setEdges, setNodes] [setEdges, setNodes]
); );
const onclickSyncVersion = useCallback(async () => { const onClickSyncVersion = useCallback(async () => {
if (!pluginId) return; if (!pluginId) return;
try { try {
setLoading(true); setLoading(true);
@@ -310,7 +356,7 @@ const MenuRender = React.memo(function MenuRender({
icon: 'common/refreshLight', icon: 'common/refreshLight',
label: t('plugin.Synchronous version'), label: t('plugin.Synchronous version'),
variant: 'whiteBase', variant: 'whiteBase',
onClick: onOpenConfirmSync(onclickSyncVersion) onClick: onOpenConfirmSync(onClickSyncVersion)
} }
] ]
: []), : []),
@@ -362,21 +408,21 @@ const MenuRender = React.memo(function MenuRender({
</> </>
); );
}, [ }, [
ConfirmDeleteModal,
ConfirmSyncModal,
DebugInputModal,
flowNodeType,
menuForbid?.copy,
menuForbid?.debug, menuForbid?.debug,
menuForbid?.copy,
menuForbid?.delete, menuForbid?.delete,
t,
flowNodeType,
onOpenConfirmSync,
onClickSyncVersion,
onOpenConfirmDeleteNode,
ConfirmSyncModal,
ConfirmDeleteModal,
DebugInputModal,
openDebugNode,
nodeId, nodeId,
onCopyNode, onCopyNode,
onDelNode, onDelNode
onOpenConfirmDeleteNode,
onOpenConfirmSync,
onclickSyncVersion,
openDebugNode,
t
]); ]);
return Render; return Render;

View File

@@ -19,6 +19,7 @@ export const flowNode2StoreNodes = ({
flowNodeType: item.data.flowNodeType, flowNodeType: item.data.flowNodeType,
showStatus: item.data.showStatus, showStatus: item.data.showStatus,
position: item.position, position: item.position,
version: item.data.version,
inputs: item.data.inputs, inputs: item.data.inputs,
outputs: item.data.outputs, outputs: item.data.outputs,
pluginId: item.data.pluginId pluginId: item.data.pluginId

View File

@@ -22,6 +22,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
intro: plugin.intro, intro: plugin.intro,
showStatus: true, showStatus: true,
isTool: plugin.isTool, isTool: plugin.isTool,
version: '481',
inputs: [], inputs: [],
outputs: [] outputs: []
})) || []; })) || [];

View File

@@ -47,6 +47,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
name: plugin.name, name: plugin.name,
intro: plugin.intro, intro: plugin.intro,
showStatus: false, showStatus: false,
version: '481',
inputs: [], inputs: [],
outputs: [] outputs: []
})); }));

View File

@@ -39,6 +39,7 @@ export const defaultForm: EditFormType = {
x: 616.4226348688949, x: 616.4226348688949,
y: -165.05298493910115 y: -165.05298493910115
}, },
version: '481',
inputs: [], inputs: [],
outputs: [] outputs: []
}, },
@@ -52,6 +53,7 @@ export const defaultForm: EditFormType = {
x: 1607.7142331269126, x: 1607.7142331269126,
y: -151.8669210746189 y: -151.8669210746189
}, },
version: '481',
inputs: [], inputs: [],
outputs: [] outputs: []
} }

View File

@@ -26,6 +26,7 @@ export const appTemplates: (AppItemType & {
x: 531.2422736065552, x: 531.2422736065552,
y: -486.7611729549753 y: -486.7611729549753
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'welcomeText', key: 'welcomeText',
@@ -88,6 +89,7 @@ export const appTemplates: (AppItemType & {
x: 558.4082376415505, x: 558.4082376415505,
y: 123.72387429194112 y: 123.72387429194112
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'userChatInput', key: 'userChatInput',
@@ -119,6 +121,7 @@ export const appTemplates: (AppItemType & {
x: 1097.7317280958762, x: 1097.7317280958762,
y: -244.16014496351386 y: -244.16014496351386
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'model', key: 'model',
@@ -253,6 +256,7 @@ export const appTemplates: (AppItemType & {
x: 496.57560693988853, x: 496.57560693988853,
y: -490.7611729549753 y: -490.7611729549753
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'welcomeText', key: 'welcomeText',
@@ -332,6 +336,7 @@ export const appTemplates: (AppItemType & {
x: 558.4082376415505, x: 558.4082376415505,
y: 123.72387429194112 y: 123.72387429194112
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'userChatInput', key: 'userChatInput',
@@ -363,6 +368,7 @@ export const appTemplates: (AppItemType & {
x: 1097.7317280958762, x: 1097.7317280958762,
y: -244.16014496351386 y: -244.16014496351386
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'model', key: 'model',
@@ -497,6 +503,7 @@ export const appTemplates: (AppItemType & {
x: 531.2422736065552, x: 531.2422736065552,
y: -486.7611729549753 y: -486.7611729549753
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'welcomeText', key: 'welcomeText',
@@ -559,6 +566,7 @@ export const appTemplates: (AppItemType & {
x: 558.4082376415505, x: 558.4082376415505,
y: 123.72387429194112 y: 123.72387429194112
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'userChatInput', key: 'userChatInput',
@@ -590,6 +598,7 @@ export const appTemplates: (AppItemType & {
x: 1638.509551404687, x: 1638.509551404687,
y: -341.0428450861567 y: -341.0428450861567
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'model', key: 'model',
@@ -709,6 +718,7 @@ export const appTemplates: (AppItemType & {
x: 918.5901682164496, x: 918.5901682164496,
y: -227.11542247619582 y: -227.11542247619582
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'datasets', key: 'datasets',
@@ -821,6 +831,7 @@ export const appTemplates: (AppItemType & {
x: 531.2422736065552, x: 531.2422736065552,
y: -486.7611729549753 y: -486.7611729549753
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'welcomeText', key: 'welcomeText',
@@ -883,6 +894,7 @@ export const appTemplates: (AppItemType & {
x: 558.4082376415505, x: 558.4082376415505,
y: 123.72387429194112 y: 123.72387429194112
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'userChatInput', key: 'userChatInput',
@@ -914,6 +926,7 @@ export const appTemplates: (AppItemType & {
x: 2701.1267277679685, x: 2701.1267277679685,
y: -767.8956312653042 y: -767.8956312653042
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'model', key: 'model',
@@ -1034,6 +1047,7 @@ export const appTemplates: (AppItemType & {
x: 1020.9667229609946, x: 1020.9667229609946,
y: -385.0060974413916 y: -385.0060974413916
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'model', key: 'model',
@@ -1114,6 +1128,7 @@ export const appTemplates: (AppItemType & {
x: 1874.9167551056487, x: 1874.9167551056487,
y: 434.98431875888207 y: 434.98431875888207
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'text', key: 'text',
@@ -1139,6 +1154,7 @@ export const appTemplates: (AppItemType & {
x: 1851.010152279949, x: 1851.010152279949,
y: -613.3555232387284 y: -613.3555232387284
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'datasets', key: 'datasets',

View File

@@ -27,6 +27,7 @@ export function form2AppWorkflow(data: AppSimpleEditFormType): WorkflowType {
x: 531.2422736065552, x: 531.2422736065552,
y: -486.7611729549753 y: -486.7611729549753
}, },
version: '481',
inputs: [ inputs: [
{ {
key: NodeInputKeyEnum.welcomeText, key: NodeInputKeyEnum.welcomeText,
@@ -79,6 +80,7 @@ export function form2AppWorkflow(data: AppSimpleEditFormType): WorkflowType {
x: 558.4082376415505, x: 558.4082376415505,
y: 123.72387429194112 y: 123.72387429194112
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'userChatInput', key: 'userChatInput',
@@ -115,6 +117,7 @@ export function form2AppWorkflow(data: AppSimpleEditFormType): WorkflowType {
x: 1106.3238387960757, x: 1106.3238387960757,
y: -350.6030674683474 y: -350.6030674683474
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'model', key: 'model',
@@ -247,6 +250,7 @@ export function form2AppWorkflow(data: AppSimpleEditFormType): WorkflowType {
x: 1638.509551404687, x: 1638.509551404687,
y: -341.0428450861567 y: -341.0428450861567
}, },
version: '481', // [FlowNodeTypeEnum.chatNode]
inputs: [ inputs: [
{ {
key: 'model', key: 'model',
@@ -366,6 +370,7 @@ export function form2AppWorkflow(data: AppSimpleEditFormType): WorkflowType {
x: 918.5901682164496, x: 918.5901682164496,
y: -227.11542247619582 y: -227.11542247619582
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'datasets', key: 'datasets',
@@ -484,6 +489,7 @@ export function form2AppWorkflow(data: AppSimpleEditFormType): WorkflowType {
x: 500, x: 500,
y: 545 y: 545
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'datasets', key: 'datasets',
@@ -597,6 +603,7 @@ export function form2AppWorkflow(data: AppSimpleEditFormType): WorkflowType {
x: 500 + 500 * (i + 1), x: 500 + 500 * (i + 1),
y: 545 y: 545
}, },
version: tool.version,
inputs: tool.inputs, inputs: tool.inputs,
outputs: tool.outputs outputs: tool.outputs
} }
@@ -625,6 +632,7 @@ export function form2AppWorkflow(data: AppSimpleEditFormType): WorkflowType {
x: 1062.1738942532802, x: 1062.1738942532802,
y: -223.65033022650476 y: -223.65033022650476
}, },
version: '481',
inputs: [ inputs: [
{ {
key: 'model', key: 'model',

View File

@@ -39,6 +39,7 @@ export const getGlobalVariableNode = (nodes: FlowNodeItemType[], t: TFunction) =
intro: '', intro: '',
unique: true, unique: true,
forbidDelete: true, forbidDelete: true,
version: '481',
inputs: [], inputs: [],
outputs: [] outputs: []
}; };
@@ -418,6 +419,7 @@ export const v1Workflow2V2 = (
pluginId, pluginId,
pluginType: node.pluginType, pluginType: node.pluginType,
parentId: node.parentId, parentId: node.parentId,
version: 'v2.0',
inputs, inputs,
outputs outputs

View File

@@ -24,7 +24,11 @@ import {
} from '@fastgpt/global/core/workflow/utils'; } from '@fastgpt/global/core/workflow/utils';
import { getSystemVariables } from '../app/utils'; import { getSystemVariables } from '../app/utils';
import { TFunction } from 'next-i18next'; import { TFunction } from 'next-i18next';
import { ReferenceValueProps } from '@fastgpt/global/core/workflow/type/io'; import {
FlowNodeInputItemType,
FlowNodeOutputItemType,
ReferenceValueProps
} from '@fastgpt/global/core/workflow/type/io';
import { IfElseListItemType } from '@fastgpt/global/core/workflow/template/system/ifElse/type'; import { IfElseListItemType } from '@fastgpt/global/core/workflow/template/system/ifElse/type';
import { VariableConditionEnum } from '@fastgpt/global/core/workflow/template/system/ifElse/constant'; import { VariableConditionEnum } from '@fastgpt/global/core/workflow/template/system/ifElse/constant';
@@ -87,7 +91,8 @@ export const storeNode2FlowNode = ({
...templateOutput, ...templateOutput,
value: storeOutput.value value: storeOutput.value
}; };
}) }),
version: storeNode.version || '481'
}; };
return { return {
@@ -298,3 +303,34 @@ export const getWorkflowGlobalVariables = (
return [...globalVariables, ...systemVariables]; return [...globalVariables, ...systemVariables];
}; };
export type CombinedItemType = Partial<FlowNodeInputItemType> & Partial<FlowNodeOutputItemType>;
export const updateFlowNodeVersion = (
node: FlowNodeItemType,
template: FlowNodeTemplateType
): FlowNodeItemType => {
function updateArrayBasedOnTemplate<T extends FlowNodeInputItemType | FlowNodeOutputItemType>(
nodeArray: T[],
templateArray: T[]
): T[] {
return templateArray.map((templateItem) => {
const nodeItem = nodeArray.find((item) => item.key === templateItem.key);
if (nodeItem) {
return { ...templateItem, ...nodeItem } as T;
}
return { ...templateItem };
});
}
const updatedNode: FlowNodeItemType = { ...node, ...template, name: node.name };
if (node.inputs && template.inputs) {
updatedNode.inputs = updateArrayBasedOnTemplate(node.inputs, template.inputs);
}
if (node.outputs && template.outputs) {
updatedNode.outputs = updateArrayBasedOnTemplate(node.outputs, template.outputs);
}
return updatedNode;
};