perf: workflow type

This commit is contained in:
archer 2025-06-24 16:50:13 +08:00
parent 5b294c4513
commit 491045557e
No known key found for this signature in database
GPG Key ID: 4446499B846D4A9E
81 changed files with 375 additions and 1283 deletions

View File

@ -8,7 +8,7 @@ import { WorkflowIOValueTypeEnum } from '../../workflow/constants';
import { PluginInputModule } from '../../workflow/template/system/pluginInput';
import { PluginOutputModule } from '../../workflow/template/system/pluginOutput';
import { HttpNode468 } from '../../workflow/template/system/http468';
import { type HttpParamAndHeaderItemType } from '../../workflow/api';
import { type HttpParamAndHeaderItemType } from '../../workflow/type/io';
import { type StoreNodeItemType } from '../../workflow/type/node';
import { HttpImgUrl } from '../../../common/file/image/constants';
import SwaggerParser from '@apidevtools/swagger-parser';

View File

@ -0,0 +1,7 @@
export enum PluginSourceEnum {
personal = 'personal', // this is a app.
systemTool = 'systemTool', // FastGPT-plugin tools, pure code.
commercial = 'commercial', // configured in Pro, with associatedPluginId. Specially, commercial-dalle3 is a systemTool
// @deprecated
community = 'community' // this is deprecated, will be replaced by systemTool
}

View File

@ -0,0 +1,56 @@
import type { StoreEdgeItemType } from 'core/workflow/type/edge';
import { ModuleTemplateTypeEnum } from '../../workflow/constants';
import type { StoreNodeItemType } from '../../workflow/type/node';
import type { PluginSourceEnum } from './constants';
import { MethodType } from './controller';
import type { FlowNodeTemplateType } from '../../workflow/type/node';
import type { WorkflowTemplateType } from '../../workflow/type';
import type { FlowNodeInputItemType, FlowNodeOutputItemType } from '../../workflow/type/io';
export type PluginRuntimeType = {
id: string;
teamId?: string;
tmbId?: string;
name: string;
avatar: string;
showStatus?: boolean;
isTool?: boolean;
nodes: StoreNodeItemType[];
edges: StoreEdgeItemType[];
currentCost?: number;
hasTokenFee?: boolean;
};
// system plugin
export type SystemPluginTemplateItemType = WorkflowTemplateType & {
templateType: string;
// FastGPT-plugin tool
inputs?: FlowNodeInputItemType[];
outputs?: FlowNodeOutputItemType[];
// Admin workflow tool
associatedPluginId?: string;
userGuide?: string;
// commercial plugin config
originCost?: number; // n points/one time
currentCost?: number;
hasTokenFee?: boolean;
pluginOrder?: number;
isActive?: boolean;
isOfficial?: boolean;
// Admin config
inputList?: FlowNodeInputItemType['inputList'];
hasSystemSecret?: boolean;
};
export type SystemPluginTemplateListItemType = Omit<
SystemPluginTemplateItemType,
'name' | 'intro'
> & {
name: string;
intro: string;
};

View File

@ -6,7 +6,7 @@ import type {
VariableInputEnum,
WorkflowIOValueTypeEnum
} from '../workflow/constants';
import type { SelectedDatasetType } from '../workflow/api';
import type { SelectedDatasetType } from '../workflow/type/io';
import type { DatasetSearchModeEnum } from '../dataset/constants';
import { TeamTagSchema as TeamTagsSchemaType } from '@fastgpt/global/support/user/team/type.d';
import type { StoreEdgeItemType } from '../workflow/type/edge';

View File

@ -1,27 +0,0 @@
export enum PluginTypeEnum {
folder = 'folder',
custom = 'custom',
http = 'http'
}
export const pluginTypeMap = {
[PluginTypeEnum.folder]: {
label: '文件夹',
icon: 'file/fill/folder'
},
[PluginTypeEnum.custom]: {
label: '自定义',
icon: 'common/custom'
},
[PluginTypeEnum.http]: {
label: 'HTTP',
icon: 'common/http'
}
};
export enum PluginSourceEnum {
personal = 'personal', // this is a app.
systemTool = 'systemTool', // FastGPT-plugin tools, pure code.
commercial = 'commercial', // configured in Pro, with associatedPluginId. Specially, commercial-dalle3 is a systemTool
// @deprecated
community = 'community' // this is deprecated, will be replaced by systemTool
}

View File

@ -1,42 +0,0 @@
import type { StoreEdgeItemType } from 'core/workflow/type/edge';
import type { StoreNodeItemType } from '../workflow/type/node';
import type { PluginTypeEnum } from './constants';
import { HttpAuthMethodType } from '../app/httpPlugin/type';
export type CreateOnePluginParams = {
name: string;
avatar: string;
intro: string;
modules: StoreNodeItemType[];
parentId: string | null;
type: `${PluginTypeEnum}`;
metadata?: {
apiSchemaStr?: string;
customHeaders?: string;
};
};
export type UpdatePluginParams = {
id: string;
parentId?: string | null;
name?: string;
avatar?: string;
intro?: string;
modules?: StoreNodeItemType[];
edges?: StoreEdgeItemType[];
metadata?: {
apiSchemaStr?: string;
customHeaders?: string;
};
};
export type PluginListItemType = {
_id: string;
parentId: string;
type: `${PluginTypeEnum}`;
name: string;
avatar: string;
intro: string;
metadata?: {
apiSchemaStr?: string;
customHeaders?: string;
};
};

View File

@ -1,54 +0,0 @@
import type { StoreEdgeItemType } from 'core/workflow/type/edge';
import { ModuleTemplateTypeEnum } from '../workflow/constants';
import type { StoreNodeItemType } from '../workflow/type/node';
import type { PluginSourceEnum, PluginTypeEnum } from './constants';
import { MethodType } from './controller';
import type { FlowNodeTemplateType } from '../workflow/type/node';
export type PluginItemSchema = {
_id: string;
userId: string;
teamId: string;
tmbId: string;
name: string;
avatar: string;
intro: string;
updateTime: Date;
modules: StoreNodeItemType[];
edges: StoreEdgeItemType[];
parentId: string;
type: `${PluginTypeEnum}`;
metadata?: {
pluginUid?: string;
apiSchemaStr?: string;
customHeaders?: string;
};
version?: 'v1' | 'v2';
nodeVersion?: string;
inited?: boolean;
};
/* plugin template */
export type PluginTemplateType = PluginRuntimeType & {
author?: string;
id: string;
source: PluginSourceEnum;
templateType: FlowNodeTemplateType['templateType'];
intro: string;
version: string;
};
export type PluginRuntimeType = {
id: string;
teamId?: string;
tmbId?: string;
name: string;
avatar: string;
showStatus?: boolean;
isTool?: boolean;
nodes: StoreNodeItemType[];
edges: StoreEdgeItemType[];
currentCost?: number;
hasTokenFee?: boolean;
};

View File

@ -1,27 +0,0 @@
import type { EmbeddingModelItemType } from '../ai/model.d';
import { NodeInputKeyEnum } from './constants';
export type SelectedDatasetType = {
datasetId: string;
avatar: string;
name: string;
vectorModel: EmbeddingModelItemType;
}[];
export type HttpBodyType<T = Record<string, any>> = {
// [NodeInputKeyEnum.addInputParam]: Record<string, any>;
} & T;
export type HttpQueryType = {
appId: string;
chatId?: string;
responseChatItemId?: string;
variables: Record<string, any>;
[key: string]: any;
};
/* http node */
export type HttpParamAndHeaderItemType = {
key: string;
type: string;
value: string;
};

View File

@ -1,17 +0,0 @@
import { type FlowNodeInputItemType } from '../../type/io';
export const getInputComponentProps = (input: FlowNodeInputItemType) => {
return {
referencePlaceholder: input.referencePlaceholder,
placeholder: input.placeholder,
maxLength: input.maxLength,
list: input.list,
markList: input.markList,
step: input.step,
max: input.max,
min: input.min,
defaultValue: input.defaultValue,
llmModelType: input.llmModelType,
customInputConfig: input.customInputConfig
};
};

View File

@ -94,17 +94,16 @@ export type RuntimeNodeItemType = {
intro?: StoreNodeItemType['intro'];
flowNodeType: StoreNodeItemType['flowNodeType'];
showStatus?: StoreNodeItemType['showStatus'];
toolConfig?: StoreNodeItemType['toolConfig'];
isEntry?: boolean;
version?: string;
inputs: FlowNodeInputItemType[];
outputs: FlowNodeOutputItemType[];
pluginId?: string; // workflow id / plugin id
version?: string;
// tool
toolConfig?: NodeToolConfigType;
// Tool
toolConfig?: StoreNodeItemType['toolConfig'];
};
export type RuntimeEdgeItemType = StoreEdgeItemType & {

View File

@ -12,15 +12,14 @@ import {
FlowNodeTemplateTypeEnum
} from '../../../../constants';
import { Input_Template_History, Input_Template_UserChatInput } from '../../../input';
import { getHandleConfig } from '../../../utils';
import { i18nT } from '../../../../../../../web/i18n/utils';
export const RunAppModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.runApp,
templateType: FlowNodeTemplateTypeEnum.tools,
flowNodeType: FlowNodeTypeEnum.runApp,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
avatar: 'core/workflow/template/runApp',
name: i18nT('workflow:application_call'),
intro: i18nT('workflow:select_another_application_to_call'),

View File

@ -19,7 +19,6 @@ import {
Input_Template_UserChatInput,
Input_Template_File_Link
} from '../../input';
import { getHandleConfig } from '../../utils';
import { i18nT } from '../../../../../../web/i18n/utils';
export const AiChatQuoteRole = {
@ -46,8 +45,8 @@ export const AiChatModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.chatNode,
templateType: FlowNodeTemplateTypeEnum.ai,
flowNodeType: FlowNodeTypeEnum.chatNode,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
avatar: 'core/workflow/template/aiChat',
name: i18nT('workflow:template.ai_chat'),
intro: i18nT('workflow:template.ai_chat_intro'),

View File

@ -5,15 +5,14 @@ import {
NodeInputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import { getHandleConfig } from '../utils';
import { i18nT } from '../../../../../web/i18n/utils';
export const AssignedAnswerModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.answerNode,
templateType: FlowNodeTemplateTypeEnum.tools,
flowNodeType: FlowNodeTypeEnum.answerNode,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
avatar: 'core/workflow/template/reply',
name: i18nT('workflow:assigned_reply'),
intro: i18nT('workflow:intro_assigned_reply'),

View File

@ -17,15 +17,14 @@ import {
} from '../../input';
import { Input_Template_System_Prompt } from '../../input';
import { LLMModelTypeEnum } from '../../../../ai/constants';
import { getHandleConfig } from '../../utils';
import { i18nT } from '../../../../../../web/i18n/utils';
export const ClassifyQuestionModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.classifyQuestion,
templateType: FlowNodeTemplateTypeEnum.ai,
flowNodeType: FlowNodeTypeEnum.classifyQuestion,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(true, false, true, true),
showSourceHandle: false,
showTargetHandle: true,
avatar: 'core/workflow/template/questionClassify',
name: i18nT('workflow:question_classification'),
intro: i18nT('workflow:intro_question_classification'),

View File

@ -5,14 +5,13 @@ import {
NodeInputKeyEnum,
WorkflowIOValueTypeEnum
} from '../../constants';
import { getHandleConfig } from '../utils';
export const CommentNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.comment,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowNodeType: FlowNodeTypeEnum.comment,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(false, false, false, false),
showSourceHandle: false,
showTargetHandle: false,
avatar: '',
name: '',
intro: '',

View File

@ -12,15 +12,14 @@ import {
} from '../../../constants';
import { Input_Template_SelectAIModel, Input_Template_History } from '../../input';
import { LLMModelTypeEnum } from '../../../../ai/constants';
import { getHandleConfig } from '../../utils';
import { i18nT } from '../../../../../../web/i18n/utils';
export const ContextExtractModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.contentExtract,
templateType: FlowNodeTemplateTypeEnum.ai,
flowNodeType: FlowNodeTypeEnum.contentExtract,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
avatar: 'core/workflow/template/extractJson',
name: i18nT('workflow:text_content_extraction'),
intro: i18nT('workflow:intro_text_content_extraction'),

View File

@ -5,15 +5,14 @@ import {
FlowNodeTemplateTypeEnum,
NodeInputKeyEnum
} from '../../constants';
import { getHandleConfig } from '../utils';
import { i18nT } from '../../../../../web/i18n/utils';
export const CustomFeedbackNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.customFeedback,
templateType: FlowNodeTemplateTypeEnum.other,
flowNodeType: FlowNodeTypeEnum.customFeedback,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
avatar: 'core/workflow/template/customFeedback',
name: i18nT('workflow:custom_feedback'),
intro: i18nT('workflow:intro_custom_feedback'),

View File

@ -12,7 +12,6 @@ import {
FlowNodeTemplateTypeEnum
} from '../../constants';
import { getNanoid } from '../../../../common/string/tools';
import { getHandleConfig } from '../utils';
import { type FlowNodeInputItemType } from '../../type/io.d';
import { i18nT } from '../../../../../web/i18n/utils';
@ -35,8 +34,8 @@ export const DatasetConcatModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.datasetConcatNode,
flowNodeType: FlowNodeTypeEnum.datasetConcatNode,
templateType: FlowNodeTemplateTypeEnum.other,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
avatar: 'core/workflow/template/datasetConcat',
name: i18nT('workflow:knowledge_base_search_merge'),
intro: i18nT('workflow:intro_knowledge_base_search_merge'),

View File

@ -14,7 +14,6 @@ import {
} from '../../constants';
import { Input_Template_UserChatInput } from '../input';
import { DatasetSearchModeEnum } from '../../../dataset/constants';
import { getHandleConfig } from '../utils';
import { i18nT } from '../../../../../web/i18n/utils';
export const Dataset_SEARCH_DESC = i18nT('workflow:template.dataset_search_intro');
@ -23,8 +22,8 @@ export const DatasetSearchModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.datasetSearchNode,
templateType: FlowNodeTemplateTypeEnum.ai,
flowNodeType: FlowNodeTypeEnum.datasetSearchNode,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
avatar: 'core/workflow/template/datasetSearch',
name: i18nT('workflow:template.dataset_search'),
intro: Dataset_SEARCH_DESC,

View File

@ -1,14 +1,13 @@
import { FlowNodeTypeEnum } from '../../node/constant';
import { type FlowNodeTemplateType } from '../../type/node';
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { getHandleConfig } from '../utils';
export const EmptyNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.emptyNode,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowNodeType: FlowNodeTypeEnum.emptyNode,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(false, false, false, false),
showSourceHandle: false,
showTargetHandle: false,
avatar: '',
name: '',
intro: '',

View File

@ -13,15 +13,14 @@ import {
} from '../../constants';
import { Input_Template_DynamicInput } from '../input';
import { Output_Template_AddOutput } from '../output';
import { getHandleConfig } from '../utils';
import { i18nT } from '../../../../../web/i18n/utils';
export const HttpNode468: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.httpRequest468,
templateType: FlowNodeTemplateTypeEnum.tools,
flowNodeType: FlowNodeTypeEnum.httpRequest468,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
avatar: 'core/workflow/template/httpRequest',
name: i18nT('workflow:http_request'),
intro: i18nT('workflow:intro_http_request'),

View File

@ -11,14 +11,13 @@ import {
FlowNodeTypeEnum
} from '../../../node/constant';
import { type FlowNodeTemplateType } from '../../../type/node';
import { getHandleConfig } from '../../utils';
export const IfElseNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.ifElseNode,
templateType: FlowNodeTemplateTypeEnum.tools,
flowNodeType: FlowNodeTypeEnum.ifElseNode,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(true, false, true, true),
showSourceHandle: false,
showTargetHandle: true,
avatar: 'core/workflow/template/ifelse',
name: i18nT('workflow:condition_checker'),
intro: i18nT('workflow:execute_different_branches_based_on_conditions'),

View File

@ -11,14 +11,13 @@ import {
FlowNodeTypeEnum
} from '../../../node/constant';
import { type FlowNodeTemplateType } from '../../../type/node';
import { getHandleConfig } from '../../utils';
export const FormInputNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.formInput,
templateType: FlowNodeTemplateTypeEnum.interactive,
flowNodeType: FlowNodeTypeEnum.formInput,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
avatar: 'core/workflow/template/formInput',
name: i18nT('app:workflow.form_input'),
intro: i18nT(`app:workflow.form_input_tip`),

View File

@ -11,14 +11,13 @@ import {
FlowNodeTypeEnum
} from '../../../node/constant';
import { type FlowNodeTemplateType } from '../../../type/node.d';
import { getHandleConfig } from '../../utils';
export const UserSelectNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.userSelect,
templateType: FlowNodeTemplateTypeEnum.interactive,
flowNodeType: FlowNodeTypeEnum.userSelect,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(true, false, true, true),
showSourceHandle: false,
showTargetHandle: true,
avatar: 'core/workflow/template/userSelect',
diagram: '/imgs/app/userSelect.svg',
name: i18nT('app:workflow.user_select'),

View File

@ -12,7 +12,6 @@ import {
} from '../../constants';
import { Input_Template_DynamicInput } from '../input';
import { Output_Template_AddOutput } from '../output';
import { getHandleConfig } from '../utils';
import { i18nT } from '../../../../../web/i18n/utils';
export const nodeLafCustomInputConfig = {
@ -25,8 +24,8 @@ export const LafModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.lafModule,
templateType: FlowNodeTemplateTypeEnum.other,
flowNodeType: FlowNodeTypeEnum.lafModule,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
avatar: 'core/workflow/template/lafDispatch',
name: i18nT('workflow:laf_function_call_test'),
intro: i18nT('workflow:intro_laf_function_call'),

View File

@ -10,7 +10,6 @@ import {
NodeOutputKeyEnum,
WorkflowIOValueTypeEnum
} from '../../../constants';
import { getHandleConfig } from '../../utils';
import { i18nT } from '../../../../../../web/i18n/utils';
import {
Input_Template_Children_Node_List,
@ -23,8 +22,8 @@ export const LoopNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.loop,
templateType: FlowNodeTemplateTypeEnum.tools,
flowNodeType: FlowNodeTypeEnum.loop,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
avatar: 'core/workflow/template/loop',
name: i18nT('workflow:loop'),
intro: i18nT('workflow:intro_loop'),

View File

@ -6,14 +6,13 @@ import {
} from '../../../constants';
import { FlowNodeInputTypeEnum, FlowNodeTypeEnum } from '../../../node/constant';
import { type FlowNodeTemplateType } from '../../../type/node';
import { getHandleConfig } from '../../utils';
export const LoopEndNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.loopEnd,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowNodeType: FlowNodeTypeEnum.loopEnd,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(false, false, false, true),
showSourceHandle: false,
showTargetHandle: true,
unique: true,
forbidDelete: true,
avatar: 'core/workflow/template/loopEnd',

View File

@ -10,15 +10,14 @@ import {
NodeOutputKeyEnum,
WorkflowIOValueTypeEnum
} from '../../../constants';
import { getHandleConfig } from '../../utils';
import { i18nT } from '../../../../../../web/i18n/utils';
export const LoopStartNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.loopStart,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowNodeType: FlowNodeTypeEnum.loopStart,
sourceHandle: getHandleConfig(false, true, false, false),
targetHandle: getHandleConfig(false, false, false, false),
showSourceHandle: true,
showTargetHandle: false,
avatar: 'core/workflow/template/loopStart',
name: i18nT('workflow:loop_start'),
unique: true,

View File

@ -1,15 +1,14 @@
import { FlowNodeTypeEnum } from '../../node/constant';
import { type FlowNodeTemplateType } from '../../type/node.d';
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { getHandleConfig } from '../utils';
import { i18nT } from '../../../../../web/i18n/utils';
export const PluginConfigNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.pluginConfig,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowNodeType: FlowNodeTypeEnum.pluginConfig,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(false, false, false, false),
showSourceHandle: false,
showTargetHandle: false,
avatar: 'core/workflow/template/systemConfig',
name: i18nT('workflow:template.system_config'),
intro: '',

View File

@ -2,14 +2,13 @@ import { i18nT } from '../../../../../web/i18n/utils';
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { FlowNodeTypeEnum } from '../../node/constant';
import { type FlowNodeTemplateType } from '../../type/node';
import { getHandleConfig } from '../utils';
export const PluginInputModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.pluginInput,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowNodeType: FlowNodeTypeEnum.pluginInput,
sourceHandle: getHandleConfig(false, true, false, false),
targetHandle: getHandleConfig(false, false, false, false),
showSourceHandle: true,
showTargetHandle: false,
unique: true,
forbidDelete: true,
avatar: 'core/workflow/template/workflowStart',

View File

@ -2,14 +2,13 @@ import { i18nT } from '../../../../../web/i18n/utils';
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { FlowNodeTypeEnum } from '../../node/constant';
import { type FlowNodeTemplateType } from '../../type/node';
import { getHandleConfig } from '../utils';
export const PluginOutputModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.pluginOutput,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowNodeType: FlowNodeTypeEnum.pluginOutput,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(false, false, false, true),
showSourceHandle: false,
showTargetHandle: true,
unique: true,
forbidDelete: true,
avatar: 'core/workflow/template/pluginOutput',

View File

@ -15,16 +15,14 @@ import {
Input_Template_UserChatInput,
Input_Template_SelectAIModel
} from '../input';
import { LLMModelTypeEnum } from '../../../ai/constants';
import { getHandleConfig } from '../utils';
import { i18nT } from '../../../../../web/i18n/utils';
export const AiQueryExtension: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.queryExtension,
templateType: FlowNodeTemplateTypeEnum.other,
flowNodeType: FlowNodeTypeEnum.queryExtension,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
avatar: 'core/workflow/template/queryExtension',
name: i18nT('workflow:question_optimization'),
intro: i18nT('workflow:intro_question_optimization'),

View File

@ -11,14 +11,13 @@ import {
FlowNodeTypeEnum
} from '../../../node/constant';
import { type FlowNodeTemplateType } from '../../../type/node';
import { getHandleConfig } from '../../utils';
export const ReadFilesNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.readFiles,
templateType: FlowNodeTemplateTypeEnum.tools,
flowNodeType: FlowNodeTypeEnum.readFiles,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
avatar: 'core/workflow/template/readFiles',
name: i18nT('app:workflow.read_files'),
intro: i18nT('app:workflow.read_files_tip'),

View File

@ -1,14 +1,13 @@
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { FlowNodeTypeEnum } from '../../node/constant';
import { type FlowNodeTemplateType } from '../../type/node';
import { getHandleConfig } from '../utils';
export const RunAppNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.appModule,
templateType: FlowNodeTemplateTypeEnum.other,
flowNodeType: FlowNodeTypeEnum.appModule,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
intro: '',
name: '',
showStatus: false,

View File

@ -1,14 +1,13 @@
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { FlowNodeTypeEnum } from '../../node/constant';
import { type FlowNodeTemplateType } from '../../type/node';
import { getHandleConfig } from '../utils';
export const RunPluginModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.pluginModule,
templateType: FlowNodeTemplateTypeEnum.other,
flowNodeType: FlowNodeTypeEnum.pluginModule,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
intro: '',
name: '',
showStatus: false,

View File

@ -1,14 +1,13 @@
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { FlowNodeTypeEnum } from '../../node/constant';
import { type FlowNodeTemplateType } from '../../type/node';
import { getHandleConfig } from '../utils';
export const RunToolNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.tool,
templateType: FlowNodeTemplateTypeEnum.other,
flowNodeType: FlowNodeTypeEnum.tool,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
intro: '',
name: '',
showStatus: false,

View File

@ -1,18 +1,17 @@
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { FlowNodeTypeEnum } from '../../node/constant';
import { type FlowNodeTemplateType } from '../../type/node';
import { getHandleConfig } from '../utils';
export const RunToolSetNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.toolSet,
templateType: FlowNodeTemplateTypeEnum.other,
flowNodeType: FlowNodeTypeEnum.toolSet,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(false, false, false, false),
showSourceHandle: false,
showTargetHandle: false,
isTool: true,
intro: '',
name: '',
showStatus: false,
isTool: true,
inputs: [],
outputs: []
};

View File

@ -10,7 +10,6 @@ import {
FlowNodeTypeEnum
} from '../../../node/constant';
import { type FlowNodeTemplateType } from '../../../type/node';
import { getHandleConfig } from '../../utils';
import { Input_Template_DynamicInput } from '../../input';
import { Output_Template_AddOutput } from '../../output';
import { JS_TEMPLATE } from './constants';
@ -20,8 +19,8 @@ export const CodeNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.code,
templateType: FlowNodeTemplateTypeEnum.tools,
flowNodeType: FlowNodeTypeEnum.code,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
avatar: 'core/workflow/template/codeRun',
name: i18nT('workflow:code_execution'),
intro: i18nT('workflow:execute_a_simple_script_code_usually_for_complex_data_processing'),

View File

@ -1,15 +1,14 @@
import { FlowNodeTypeEnum } from '../../node/constant';
import { type FlowNodeTemplateType } from '../../type/node';
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { getHandleConfig } from '../utils';
import { i18nT } from '../../../../../web/i18n/utils';
export const StopToolNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.stopTool,
templateType: FlowNodeTemplateTypeEnum.ai,
flowNodeType: FlowNodeTypeEnum.stopTool,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: false,
showTargetHandle: true,
avatar: 'core/workflow/template/stopTool',
name: i18nT('workflow:tool_call_termination'),
intro: i18nT('workflow:intro_tool_call_termination'),

View File

@ -1,15 +1,14 @@
import { FlowNodeTypeEnum } from '../../node/constant';
import { type FlowNodeTemplateType } from '../../type/node.d';
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { getHandleConfig } from '../utils';
import { i18nT } from '../../../../../web/i18n/utils';
export const SystemConfigNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.systemConfig,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowNodeType: FlowNodeTypeEnum.systemConfig,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(false, false, false, false),
showSourceHandle: false,
showTargetHandle: false,
avatar: 'core/workflow/template/systemConfig',
name: i18nT('workflow:template.system_config'),
intro: '',

View File

@ -10,16 +10,14 @@ import {
FlowNodeTemplateTypeEnum,
NodeInputKeyEnum
} from '../../constants';
import { getHandleConfig } from '../utils';
import { Input_Template_DynamicInput } from '../input';
import { i18nT } from '../../../../../web/i18n/utils';
export const TextEditorNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.textEditor,
templateType: FlowNodeTemplateTypeEnum.tools,
flowNodeType: FlowNodeTypeEnum.textEditor,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
avatar: 'core/workflow/template/textConcat',
name: i18nT('workflow:text_concatenation'),
intro: i18nT('workflow:intro_text_concatenation'),

View File

@ -1,15 +1,14 @@
import { FlowNodeTypeEnum } from '../../node/constant';
import { type FlowNodeTemplateType } from '../../type/node';
import { FlowNodeTemplateTypeEnum } from '../../constants';
import { getHandleConfig } from '../utils';
import { i18nT } from '../../../../../web/i18n/utils';
export const ToolParamsNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.toolParams,
templateType: FlowNodeTemplateTypeEnum.ai,
flowNodeType: FlowNodeTypeEnum.toolParams,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
avatar: 'core/workflow/template/toolParams',
name: i18nT('workflow:tool_custom_field'),
intro: i18nT('workflow:intro_tool_params_config'),

View File

@ -18,7 +18,6 @@ import {
} from '../input';
import { chatNodeSystemPromptTip, systemPromptTip } from '../tip';
import { LLMModelTypeEnum } from '../../../ai/constants';
import { getHandleConfig } from '../utils';
import { i18nT } from '../../../../../web/i18n/utils';
import { Input_Template_File_Link } from '../input';
@ -26,8 +25,8 @@ export const ToolModule: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.tools,
flowNodeType: FlowNodeTypeEnum.tools,
templateType: FlowNodeTemplateTypeEnum.ai,
sourceHandle: getHandleConfig(true, true, false, true),
targetHandle: getHandleConfig(true, true, false, true),
showSourceHandle: true,
showTargetHandle: true,
avatar: 'core/workflow/template/toolCall',
name: i18nT('workflow:template.tool_call'),
intro: i18nT('workflow:template.tool_call_intro'),

View File

@ -5,15 +5,14 @@ import {
NodeInputKeyEnum,
WorkflowIOValueTypeEnum
} from '../../../constants';
import { getHandleConfig } from '../../utils';
import { i18nT } from '../../../../../../web/i18n/utils';
export const VariableUpdateNode: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.variableUpdate,
templateType: FlowNodeTemplateTypeEnum.tools,
flowNodeType: FlowNodeTypeEnum.variableUpdate,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
avatar: 'core/workflow/template/variableUpdate',
name: i18nT('workflow:variable_update'),
intro: i18nT('workflow:update_specified_node_output_or_global_variable'),

View File

@ -5,7 +5,6 @@ import {
NodeOutputKeyEnum,
FlowNodeTemplateTypeEnum
} from '../../constants';
import { getHandleConfig } from '../utils';
import { Input_Template_UserChatInput } from '../input';
import { i18nT } from '../../../../../web/i18n/utils';
import { type FlowNodeOutputItemType } from '../../type/io';
@ -23,8 +22,8 @@ export const WorkflowStart: FlowNodeTemplateType = {
id: FlowNodeTypeEnum.workflowStart,
templateType: FlowNodeTemplateTypeEnum.systemInput,
flowNodeType: FlowNodeTypeEnum.workflowStart,
sourceHandle: getHandleConfig(false, true, false, false),
targetHandle: getHandleConfig(false, false, false, false),
showSourceHandle: true,
showTargetHandle: false,
avatar: 'core/workflow/template/workflowStart',
name: i18nT('workflow:template.workflow_start'),
intro: '',

View File

@ -1,2 +1,4 @@
export const chatNodeSystemPromptTip = 'core.app.tip.chatNodeSystemPromptTip';
export const systemPromptTip = 'core.app.tip.systemPromptTip';
import { i18nT } from '../../../../web/i18n/utils';
export const chatNodeSystemPromptTip = i18nT('common:core.app.tip.chatNodeSystemPromptTip');
export const systemPromptTip = i18nT('common:core.app.tip.systemPromptTip');

View File

@ -1,6 +0,0 @@
export const getHandleConfig = (top: boolean, right: boolean, bottom: boolean, left: boolean) => ({
top,
right,
bottom,
left
});

View File

@ -1,47 +0,0 @@
import type { FlowNodeInputItemType, FlowNodeOutputItemType } from './io';
export type FlowNodeChangeProps = { nodeId: string } & (
| {
type: 'attr'; // key: attr, value: new value
key: string;
value: any;
}
| {
type: 'updateInput'; // key: update input key, value: new input value
key: string;
value: FlowNodeInputItemType;
}
| {
type: 'replaceInput'; // key: old input key, value: new input value
key: string;
value: FlowNodeInputItemType;
}
| {
type: 'addInput'; // key: null, value: new input value
value: FlowNodeInputItemType;
index?: number;
}
| {
type: 'delInput'; // key: delete input key, value: null
key: string;
}
| {
type: 'updateOutput'; // key: update output key, value: new output value
key: string;
value: FlowNodeOutputItemType;
}
| {
type: 'replaceOutput'; // key: old output key, value: new output value
key: string;
value: FlowNodeOutputItemType;
}
| {
type: 'addOutput'; // key: null, value: new output value
value: FlowNodeOutputItemType;
index?: number;
}
| {
type: 'delOutput'; // key: delete output key, value: null
key: string;
}
);

View File

@ -15,7 +15,6 @@ import {
ToolRunResponseItemType
} from '../../chat/type';
import { ChatNodeUsageType } from '../../../support/wallet/bill/type';
import { PluginTypeEnum } from '../../plugin/constants';
import type { StoreEdgeItemType } from './edge';
import type { AppChatConfigType } from '../../app/type';
import type { ParentIdType } from 'common/parentFolder/type';
@ -35,22 +34,16 @@ export type WorkflowTemplateType = {
parentId?: ParentIdType;
isFolder?: boolean;
name: I18nStringType | string;
avatar: string;
name: I18nStringType | string;
intro?: I18nStringType | string;
author?: string;
courseUrl?: string;
version?: string;
versionLabel?: string;
isLatestVersion?: boolean;
showStatus?: boolean;
weight?: number;
version?: string;
workflow: WorkflowTemplateBasicType;
inputs?: FlowNodeInputItemType[];
outputs?: FlowNodeOutputItemType[];
};
// template market
@ -68,46 +61,3 @@ export type TemplateMarketListItemType = {
type: AppTypeEnum.simple | AppTypeEnum.workflow | AppTypeEnum.plugin;
avatar: string;
};
// system plugin
export type SystemPluginTemplateItemType = WorkflowTemplateType & {
associatedPluginId?: string;
userGuide?: string;
templateType: string;
// commercial plugin config
originCost?: number; // n points/one time
currentCost?: number;
hasTokenFee?: boolean;
pluginOrder?: number;
isActive?: boolean;
isOfficial?: boolean;
// Admin config
inputList?: FlowNodeInputItemType['inputList'];
hasSystemSecret?: boolean;
};
export type SystemPluginTemplateListItemType = Omit<
SystemPluginTemplateItemType,
'name' | 'intro'
> & {
name: string;
intro: string;
};
export type THelperLine = {
position: number;
nodes: {
left: number;
right: number;
top: number;
bottom: number;
width: number;
height: number;
centerX: number;
centerY: number;
}[];
};

View File

@ -1,4 +1,4 @@
import type { LLMModelItemType } from '../../ai/model.d';
import type { EmbeddingModelItemType, LLMModelItemType } from '../../ai/model.d';
import type { LLMModelTypeEnum } from '../../ai/constants';
import type { WorkflowIOValueTypeEnum, NodeInputKeyEnum, NodeOutputKeyEnum } from '../constants';
import type { FlowNodeInputTypeEnum, FlowNodeOutputTypeEnum } from '../node/constant';
@ -11,11 +11,6 @@ export type CustomFieldConfigType = {
// reference
selectValueTypeList?: WorkflowIOValueTypeEnum[]; // 可以选哪个数据类型, 只有1个的话,则默认选择
// showIsToolParam?: boolean; // 是否作为工具参数
// showRequired?: boolean;
// defaultRequired?: boolean;
showDefaultValue?: boolean;
showDescription?: boolean;
};
@ -103,6 +98,21 @@ export type FlowNodeOutputItemType = {
deprecated?: boolean;
};
// Field value type
export type ReferenceItemValueType = [string, string | undefined];
export type ReferenceArrayValueType = ReferenceItemValueType[];
export type ReferenceValueType = ReferenceItemValueType | ReferenceArrayValueType;
export type SelectedDatasetType = {
datasetId: string;
avatar: string;
name: string;
vectorModel: EmbeddingModelItemType;
}[];
/* http node */
export type HttpParamAndHeaderItemType = {
key: string;
type: string;
value: string;
};

View File

@ -17,7 +17,6 @@ import {
} from '../../chat/type';
import { ChatNodeUsageType } from '../../../support/wallet/bill/type';
import { RuntimeNodeItemType } from '../runtime/type';
import { PluginTypeEnum } from '../../plugin/constants';
import { RuntimeEdgeItemType, StoreEdgeItemType } from './edge';
import { NextApiResponse } from 'next';
import type { AppDetailType, AppSchema, McpToolConfigType } from '../../app/type';
@ -81,9 +80,8 @@ export type FlowNodeTemplateType = FlowNodeCommonType & {
id: string; // node id, unique
templateType: string;
// show handle
sourceHandle?: HandleType;
targetHandle?: HandleType;
showSourceHandle?: boolean;
showTargetHandle?: boolean;
// tool config
currentCost?: number;
@ -100,6 +98,11 @@ export type FlowNodeTemplateType = FlowNodeCommonType & {
diagram?: string; // diagram url
courseUrl?: string; // course url
userGuide?: string; // user guide
// @deprecated
// show handle
sourceHandle?: HandleType;
targetHandle?: HandleType;
};
export type NodeTemplateListItemType = {

View File

@ -1,6 +1,5 @@
import { type FlowNodeTemplateType } from '@fastgpt/global/core/workflow/type/node.d';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import { getHandleConfig } from '@fastgpt/global/core/workflow/template/utils';
import {
appData2FlowNodeIO,
pluginData2FlowNodeIO,
@ -10,16 +9,17 @@ import {
import { MongoApp } from '../schema';
import type { localeType } from '@fastgpt/global/common/i18n/type';
import { parseI18nString } from '@fastgpt/global/common/i18n/utils';
import { type SystemPluginTemplateItemType } from '@fastgpt/global/core/workflow/type';
import type { WorkflowTemplateBasicType } from '@fastgpt/global/core/workflow/type';
import { type SystemPluginTemplateItemType } from '@fastgpt/global/core/app/plugin/type';
import {
checkIsLatestVersion,
getAppLatestVersion,
getAppVersionById
} from '../version/controller';
import { type PluginRuntimeType } from '@fastgpt/global/core/plugin/type';
import { type PluginRuntimeType } from '@fastgpt/global/core/app/plugin/type';
import { MongoSystemPlugin } from './systemPluginSchema';
import { PluginErrEnum } from '@fastgpt/global/common/error/code/plugin';
import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants';
import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants';
import {
FlowNodeTemplateTypeEnum,
NodeInputKeyEnum
@ -58,6 +58,9 @@ export function splitCombineToolId(id: string) {
type ChildAppType = SystemPluginTemplateItemType & {
teamId?: string;
tmbId?: string;
workflow?: WorkflowTemplateBasicType;
versionLabel?: string; // Auto computed
isLatestVersion?: boolean; // Auto computed
};
export const getSystemPluginByIdAndVersionId = async (
@ -67,6 +70,7 @@ export const getSystemPluginByIdAndVersionId = async (
const plugin = await (async () => {
const plugin = await getSystemPluginById(pluginId);
// Admin selected system tool
if (plugin.associatedPluginId) {
// The verification plugin is set as a system plugin
const systemPlugin = await MongoSystemPlugin.findOne(
@ -166,13 +170,13 @@ export async function getChildAppPreviewNode({
currentCost: 0,
hasTokenFee: false,
pluginOrder: 0
} as ChildAppType;
};
} else {
return getSystemPluginByIdAndVersionId(pluginId, versionId);
}
})();
const { flowNodeType, nodeIOConfig } = (() => {
const { flowNodeType, nodeIOConfig } = await (async () => {
if (source === PluginSourceEnum.systemTool) {
return {
flowNodeType: FlowNodeTypeEnum.tool,
@ -231,14 +235,14 @@ export async function getChildAppPreviewNode({
intro: parseI18nString(app.intro, lang),
courseUrl: app.courseUrl,
userGuide: app.userGuide,
showStatus: app.showStatus,
showStatus: true,
isTool: true,
version: app.version,
versionLabel: app.versionLabel,
isLatestVersion: app.isLatestVersion,
sourceHandle: getHandleConfig(true, true, true, true),
targetHandle: getHandleConfig(true, true, true, true),
showSourceHandle: true,
showTargetHandle: true,
currentCost: app.currentCost,
hasTokenFee: app.hasTokenFee,
@ -292,7 +296,6 @@ export async function getChildAppRuntimeById(
pluginOrder: 0
};
} else {
// System
return getSystemPluginByIdAndVersionId(pluginId, versionId);
}
})();
@ -303,7 +306,7 @@ export async function getChildAppRuntimeById(
tmbId: app.tmbId,
name: parseI18nString(app.name, lang),
avatar: app.avatar || '',
showStatus: app.showStatus,
showStatus: true,
currentCost: app.currentCost,
nodes: app.workflow.nodes,
edges: app.workflow.edges,
@ -312,17 +315,8 @@ export async function getChildAppRuntimeById(
}
const dbPluginFormat = (item: SystemPluginConfigSchemaType): SystemPluginTemplateItemType => {
const {
name,
avatar,
intro,
version,
weight,
workflow,
templateType,
associatedPluginId,
userGuide
} = item.customConfig!;
const { name, avatar, intro, version, weight, templateType, associatedPluginId, userGuide } =
item.customConfig!;
return {
id: item.pluginId,
@ -334,16 +328,18 @@ const dbPluginFormat = (item: SystemPluginConfigSchemaType): SystemPluginTemplat
name,
avatar,
intro,
showStatus: true,
weight,
templateType,
workflow,
originCost: item.originCost,
currentCost: item.currentCost,
hasTokenFee: item.hasTokenFee,
pluginOrder: item.pluginOrder,
associatedPluginId,
userGuide
userGuide,
workflow: {
nodes: [],
edges: []
}
};
};
@ -456,9 +452,8 @@ export const getSystemPluginById = async (
const tool = tools.find((item) => item.id === pluginId);
if (tool) {
return tool;
} else {
return Promise.reject(PluginErrEnum.unExist);
}
return Promise.reject(PluginErrEnum.unExist);
}
const dbPlugin = await MongoSystemPlugin.findOne({ pluginId }).lean();

View File

@ -1,9 +1,6 @@
import { SystemPluginListItemType } from '@fastgpt/global/core/app/type';
import { FlowNodeTemplateTypeEnum } from '@fastgpt/global/core/workflow/constants';
import type {
SystemPluginTemplateItemType,
WorkflowTemplateBasicType
} from '@fastgpt/global/core/workflow/type';
import type { WorkflowTemplateBasicType } from '@fastgpt/global/core/workflow/type';
export type SystemPluginConfigSchemaType = {
pluginId: string;
@ -20,7 +17,6 @@ export type SystemPluginConfigSchemaType = {
intro?: string;
version: string;
weight?: number;
workflow: WorkflowTemplateBasicType;
templateType: string;
associatedPluginId: string;
userGuide: string;

View File

@ -1,7 +1,7 @@
import { type ChatNodeUsageType } from '@fastgpt/global/support/wallet/bill/type';
import { type PluginRuntimeType } from '@fastgpt/global/core/plugin/type';
import { type PluginRuntimeType } from '@fastgpt/global/core/app/plugin/type';
import { splitCombineToolId } from './controller';
import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants';
import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants';
/*
Plugin points calculation:

View File

@ -4,7 +4,7 @@ import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import type { StoreNodeItemType } from '@fastgpt/global/core/workflow/type/node';
import { getChildAppPreviewNode, splitCombineToolId } from './plugin/controller';
import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants';
import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants';
import { authAppByTmbId } from '../../support/permission/app/auth';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { getErrText } from '@fastgpt/global/common/error/utils';

View File

@ -1,86 +0,0 @@
import { pluginTypeMap } from '@fastgpt/global/core/plugin/constants';
import { connectionMongo, type Model } from '../../common/mongo';
const { Schema, model, models } = connectionMongo;
import type { PluginItemSchema } from '@fastgpt/global/core/plugin/type.d';
import {
TeamCollectionName,
TeamMemberCollectionName
} from '@fastgpt/global/support/user/team/constant';
export const PluginCollectionName = 'plugins';
const PluginSchema = new Schema({
parentId: {
type: Schema.Types.ObjectId,
ref: PluginCollectionName,
default: null
},
teamId: {
type: Schema.Types.ObjectId,
ref: TeamCollectionName,
required: true
},
tmbId: {
type: Schema.Types.ObjectId,
ref: TeamMemberCollectionName,
required: true
},
type: {
type: String,
enum: Object.keys(pluginTypeMap),
required: true
},
name: {
type: String,
required: true
},
avatar: {
type: String,
default: '/icon/logo.svg'
},
intro: {
type: String,
default: ''
},
updateTime: {
type: Date,
default: () => new Date()
},
modules: {
type: Array,
default: []
},
edges: {
type: Array,
default: []
},
metadata: {
type: {
pluginUid: String,
apiSchemaStr: String,
customHeaders: String
}
},
version: {
type: String,
enum: ['v1', 'v2']
},
nodeVersion: {
type: String,
default: ''
},
inited: Boolean
});
try {
PluginSchema.index({ type: 1, init: 1 });
PluginSchema.index({ teamId: 1, parentId: 1 });
PluginSchema.index({ teamId: 1, name: 1, intro: 1 });
} catch (error) {
console.log(error);
}
export const MongoPlugin: Model<PluginItemSchema> =
models[PluginCollectionName] || model(PluginCollectionName, PluginSchema);
MongoPlugin.syncIndexes();

View File

@ -3,7 +3,7 @@ import {
type DispatchNodeResultType
} from '@fastgpt/global/core/workflow/runtime/type.d';
import { formatModelChars2Points } from '../../../../support/wallet/usage/utils';
import type { SelectedDatasetType } from '@fastgpt/global/core/workflow/api.d';
import type { SelectedDatasetType } from '@fastgpt/global/core/workflow/type/io';
import type { SearchDataResponseItemType } from '@fastgpt/global/core/dataset/type';
import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/type';
import { getEmbeddingModel, getRerankModel } from '../../../ai/model';

View File

@ -1,6 +1,6 @@
import { getPluginInputsFromStoreNodes } from '@fastgpt/global/core/app/plugin/utils';
import { chatValue2RuntimePrompt } from '@fastgpt/global/core/chat/adapt';
import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants';
import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants';
import type { ModuleDispatchProps } from '@fastgpt/global/core/workflow/runtime/type';
@ -37,15 +37,7 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
return Promise.reject('pluginId can not find');
}
const { files } = chatValue2RuntimePrompt(query);
// auth plugin
const pluginData = await authPluginByTmbId({
appId: pluginId,
tmbId: runningAppInfo.tmbId,
per: ReadPermissionVal
});
// Adapt <= 4.10 system tool
const { source } = splitCombineToolId(pluginId);
if (source === PluginSourceEnum.systemTool) {
return dispatchRunTool({
@ -61,6 +53,19 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
});
}
/*
1. Team app
2. Admin selected system tool
*/
const { files } = chatValue2RuntimePrompt(query);
// auth plugin
const pluginData = await authPluginByTmbId({
appId: pluginId,
tmbId: runningAppInfo.tmbId,
per: ReadPermissionVal
});
const plugin = await getChildAppRuntimeById(pluginId, version);
const outputFilterMap =

View File

@ -11,7 +11,7 @@ import { type PermissionValueType } from '@fastgpt/global/support/permission/typ
import { AppFolderTypeList } from '@fastgpt/global/core/app/constants';
import { type ParentIdType } from '@fastgpt/global/common/parentFolder/type';
import { splitCombineToolId } from '../../../core/app/plugin/controller';
import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants';
import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants';
import { type AuthModeType, type AuthResponseType } from '../type';
import { AppDefaultPermissionVal } from '@fastgpt/global/support/permission/app/constant';

View File

@ -1,7 +1,7 @@
import fs from 'fs';
import path from 'path';
import { isProduction } from '@fastgpt/global/common/system/constants';
import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants';
import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants';
import { MongoAppTemplate } from '@fastgpt/service/core/app/templates/templateSchema';
import { type AppTemplateSchemaType } from '@fastgpt/global/core/app/type';

View File

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

View File

@ -1,4 +1,4 @@
import { type THelperLine } from '@fastgpt/global/core/workflow/type';
import { type THelperLine } from '@/web/core/workflow/type';
import { type CSSProperties, useEffect, useRef } from 'react';
import { type ReactFlowState, useStore, useViewport } from 'reactflow';

View File

@ -21,7 +21,7 @@ import { useTranslation } from 'next-i18next';
import { useKeyboard } from './useKeyboard';
import { useContextSelector } from 'use-context-selector';
import { WorkflowContext } from '../../context';
import { type THelperLine } from '@fastgpt/global/core/workflow/type';
import { type THelperLine } from '@/web/core/workflow/type';
import { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import { useDebounceEffect, useMemoizedFn } from 'ahooks';
import { type FlowNodeItemType } from '@fastgpt/global/core/workflow/type/node';

View File

@ -44,7 +44,7 @@ export const ConnectionSourceHandle = ({
*/
if (
!(isFoldNode && node?.outputs.length) &&
(!node || !node?.sourceHandle?.right || rightTargetConnected)
(!node || !node?.showSourceHandle || rightTargetConnected)
)
return null;
@ -125,7 +125,7 @@ export const ConnectionTargetHandle = React.memo(function ConnectionTargetHandle
})();
const LeftHandle = (() => {
if (!node || !node?.targetHandle?.left) return null;
if (!node || !node?.showTargetHandle) return null;
const handleId = getHandleId(nodeId, 'target', Position.Left);

View File

@ -12,7 +12,7 @@ import {
import { useContextSelector } from 'use-context-selector';
import { WorkflowContext } from '@/pageComponents/app/detail/WorkflowComponents/context';
import { defaultInput } from '../../FieldEditModal';
import { getInputComponentProps } from '@fastgpt/global/core/workflow/node/io/utils';
import { getInputComponentProps } from '@/web/core/workflow/utils';
import { ReferSelector, useReference } from '../Reference';
import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
import ValueTypeLabel from '../../../ValueTypeLabel';

View File

@ -1,7 +1,7 @@
import React, { useEffect, useMemo, useState } from 'react';
import type { RenderInputProps } from '../type';
import { Box, Button, Flex, Grid, Switch, useDisclosure, useTheme } from '@chakra-ui/react';
import { type SelectedDatasetType } from '@fastgpt/global/core/workflow/api';
import { type SelectedDatasetType } from '@fastgpt/global/core/workflow/type/io';
import Avatar from '@fastgpt/web/components/common/Avatar';
import { useTranslation } from 'next-i18next';
import { DatasetSearchModeEnum } from '@fastgpt/global/core/dataset/constants';

View File

@ -7,7 +7,6 @@ import {
} from '@/web/core/workflow/utils';
import { getErrText } from '@fastgpt/global/common/error/utils';
import { NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import { type RuntimeNodeItemType } from '@fastgpt/global/core/workflow/runtime/type';
import {
type FlowNodeItemType,
@ -18,8 +17,10 @@ import {
type RuntimeEdgeItemType,
type StoreEdgeItemType
} from '@fastgpt/global/core/workflow/type/edge';
import { type FlowNodeChangeProps } from '@fastgpt/global/core/workflow/type/fe';
import { type FlowNodeInputItemType } from '@fastgpt/global/core/workflow/type/io';
import {
type FlowNodeOutputItemType,
type FlowNodeInputItemType
} from '@fastgpt/global/core/workflow/type/io';
import { useToast } from '@fastgpt/web/hooks/useToast';
import { useMemoizedFn, useUpdateEffect } from 'ahooks';
import React, {
@ -98,6 +99,52 @@ export type WorkflowSnapshotsType = WorkflowStateType & {
diff?: any;
};
type FlowNodeChangeProps = { nodeId: string } & (
| {
type: 'attr'; // key: attr, value: new value
key: string;
value: any;
}
| {
type: 'updateInput'; // key: update input key, value: new input value
key: string;
value: FlowNodeInputItemType;
}
| {
type: 'replaceInput'; // key: old input key, value: new input value
key: string;
value: FlowNodeInputItemType;
}
| {
type: 'addInput'; // key: null, value: new input value
value: FlowNodeInputItemType;
index?: number;
}
| {
type: 'delInput'; // key: delete input key, value: null
key: string;
}
| {
type: 'updateOutput'; // key: update output key, value: new output value
key: string;
value: FlowNodeOutputItemType;
}
| {
type: 'replaceOutput'; // key: old output key, value: new output value
key: string;
value: FlowNodeOutputItemType;
}
| {
type: 'addOutput'; // key: null, value: new output value
value: FlowNodeOutputItemType;
index?: number;
}
| {
type: 'delOutput'; // key: delete output key, value: null
key: string;
}
);
type WorkflowContextType = {
appId?: string;
basicNodeTemplates: FlowNodeTemplateType[];

View File

@ -29,8 +29,8 @@ export const uiWorkflow2StoreWorkflow = ({
version: item.data.version,
inputs: item.data.inputs,
outputs: item.data.outputs,
pluginId: item.data.pluginId,
isFolded: item.data.isFolded,
pluginId: item.data.pluginId,
toolConfig: item.data.toolConfig
}));

View File

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

View File

@ -1,197 +0,0 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import { MongoPlugin } from '@fastgpt/service/core/plugin/schema';
import { MongoApp } from '@fastgpt/service/core/app/schema';
import { NextAPI } from '@/service/middleware/entry';
import { PluginTypeEnum } from '@fastgpt/global/core/plugin/constants';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { MongoAppVersion } from '@fastgpt/service/core/app/version/schema';
/*
1. HTTP plugin ,plugin,, inited
2. inited plugin,
*/
let success = 0;
async function handler(req: NextApiRequest, res: NextApiResponse) {
await authCert({ req, authRoot: true });
const { teamId } = req.body as { teamId?: string };
const total = await MongoPlugin.countDocuments({
inited: { $ne: true }
});
console.log('Total plugin', total);
await initHttp(teamId);
await initPlugin(teamId);
}
async function initHttp(teamId?: string): Promise<any> {
/* 读取http插件和他的children */
const plugin = await MongoPlugin.findOne({
...(teamId && { teamId }),
type: PluginTypeEnum.folder,
inited: { $ne: true }
}).lean();
if (!plugin) return;
const children = await MongoPlugin.find({
teamId: plugin.teamId,
parentId: plugin._id,
inited: { $ne: true }
}).lean();
await mongoSessionRun(async (session) => {
/* 创建HTTP插件作为目录 */
const [{ _id }] = await MongoApp.create(
[
{
teamId: plugin.teamId,
tmbId: plugin.tmbId,
type: AppTypeEnum.httpPlugin,
name: plugin.name,
avatar: plugin.avatar,
intro: plugin.intro,
metadata: plugin.metadata,
version: plugin.version,
pluginData: {
apiSchemaStr: plugin.metadata?.apiSchemaStr,
customHeaders: plugin.metadata?.customHeaders
}
}
],
{ session, ordered: true }
);
/* 批量创建子插件 */
for await (const item of children) {
const [{ _id: newPluginId }] = await MongoApp.create(
[
{
_id: item._id,
parentId: _id,
teamId: item.teamId,
tmbId: item.tmbId,
type: AppTypeEnum.plugin,
name: item.name,
avatar: item.avatar,
intro: item.intro,
version: plugin.version,
modules: item.modules,
edges: item.edges,
pluginData: {
nodeVersion: item.nodeVersion,
pluginUniId: plugin.metadata?.pluginUid
}
}
],
{ session, ordered: true }
);
if (item.version === 'v2') {
await MongoAppVersion.create(
[
{
tmbId: plugin.tmbId,
appId: newPluginId,
nodes: item.modules,
edges: item.edges
}
],
{ session, ordered: true }
);
}
}
/* 更新插件信息 */
await MongoPlugin.findOneAndUpdate(
{
_id: plugin._id
},
{
$set: { inited: true }
},
{ session }
);
await MongoPlugin.updateMany(
{
teamId: plugin.teamId,
parentId: plugin._id
},
{
$set: { inited: true }
},
{ session }
);
success += children.length + 1;
console.log(success);
});
return initHttp();
}
async function initPlugin(teamId?: string): Promise<any> {
const plugin = await MongoPlugin.findOne({
...(teamId && { teamId }),
type: PluginTypeEnum.custom,
inited: { $ne: true }
}).lean();
if (!plugin) return;
await mongoSessionRun(async (session) => {
const [{ _id: newPluginId }] = await MongoApp.create(
[
{
_id: plugin._id,
teamId: plugin.teamId,
tmbId: plugin.tmbId,
type: AppTypeEnum.plugin,
name: plugin.name,
avatar: plugin.avatar,
intro: plugin.intro,
version: plugin.version,
modules: plugin.modules,
edges: plugin.edges,
pluginData: {
nodeVersion: plugin.nodeVersion
}
}
],
{ session, ordered: true }
);
if (plugin.version === 'v2') {
await MongoAppVersion.create(
[
{
tmbId: plugin.tmbId,
appId: newPluginId,
nodes: plugin.modules,
edges: plugin.edges
}
],
{ session, ordered: true }
);
}
await MongoPlugin.findOneAndUpdate(
{
_id: plugin._id
},
{
$set: { inited: true }
},
{ session }
);
success++;
console.log(success);
});
return initPlugin();
}
export default NextAPI(handler);

View File

@ -1,7 +1,7 @@
/*
get plugin preview modules
*/
import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants';
import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import {
getChildAppPreviewNode,

View File

@ -10,7 +10,7 @@ import {
getSystemPluginByIdAndVersionId,
splitCombineToolId
} from '@fastgpt/service/core/app/plugin/controller';
import { PluginSourceEnum } from '@fastgpt/global/core/plugin/constants';
import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants';
import { PluginErrEnum } from '@fastgpt/global/common/error/code/plugin';
import { Types } from '@fastgpt/service/common/mongo';

View File

@ -1,72 +0,0 @@
import type { NextApiRequest, NextApiResponse } from 'next';
// @ts-ignore
import type { HttpBodyType } from '@fastgpt/global/core/module/api.d';
import { getErrText } from '@fastgpt/global/common/error/utils';
import { authRequestFromLocal } from '@fastgpt/service/support/permission/auth/common';
type Props = HttpBodyType<{
input: string;
rule?: string;
}>;
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {
const { input, rule = '' } = req.body as Props;
await authRequestFromLocal({ req });
const result = (() => {
if (typeof input === 'string') {
const defaultReg: any[] = [
'',
undefined,
'undefined',
null,
'null',
false,
'false',
0,
'0',
'none'
];
const customReg = rule.split('\n');
defaultReg.push(...customReg);
return !defaultReg.find((item) => {
const reg = typeof item === 'string' ? stringToRegex(item) : null;
if (reg) {
return reg.test(input);
}
return input === item;
});
}
return !!input;
})();
res.json({
...(result
? {
true: true
}
: {
false: false
})
});
} catch (err) {
console.log(err);
res.status(500).send(getErrText(err));
}
}
function stringToRegex(str: string) {
const regexFormat = /^\/(.+)\/([gimuy]*)$/;
const match = str.match(regexFormat);
if (match) {
const [, pattern, flags] = match;
return new RegExp(pattern, flags);
} else {
return null;
}
}

View File

@ -1,59 +0,0 @@
import type { NextApiRequest, NextApiResponse } from 'next';
//@ts-ignore
import type { HttpBodyType } from '@fastgpt/global/core/module/api.d';
import { getErrText } from '@fastgpt/global/common/error/utils';
import { addCustomFeedbacks } from '@fastgpt/service/core/chat/controller';
import { authRequestFromLocal } from '@fastgpt/service/support/permission/auth/common';
type Props = HttpBodyType<{
appId: string;
chatId?: string;
responseChatItemId?: string;
defaultFeedback: string;
customFeedback: string;
}>;
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {
const {
appId,
chatId,
responseChatItemId: dataId,
defaultFeedback,
customFeedback
} = req.body as Props;
await authRequestFromLocal({ req });
const feedback = customFeedback || defaultFeedback;
if (!feedback) {
return res.json({
response: ''
});
}
// wait the chat finish
setTimeout(() => {
addCustomFeedbacks({
appId,
chatId,
dataId,
feedbacks: [feedback]
});
}, 60000);
if (!chatId || !dataId) {
return res.json({
response: `\\n\\n**自动反馈调试**: ${feedback}\\n\\n`
});
}
return res.json({
response: ''
});
} catch (err) {
console.log(err);
res.status(500).send(getErrText(err));
}
}

View File

@ -1,59 +0,0 @@
import type { NextApiRequest, NextApiResponse } from 'next';
import type { HttpBodyType } from '@fastgpt/global/core/workflow/api.d';
import { getErrText } from '@fastgpt/global/common/error/utils';
import { addCustomFeedbacks } from '@fastgpt/service/core/chat/controller';
import { authRequestFromLocal } from '@fastgpt/service/support/permission/auth/common';
import { NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import { type SystemVariablesType } from '@fastgpt/global/core/workflow/runtime/type';
import { replaceVariable } from '@fastgpt/global/common/string/tools';
type Props = HttpBodyType<
SystemVariablesType & {
customFeedback: string;
customInputs: Record<string, any>;
}
>;
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {
const {
customFeedback,
appId,
chatId,
responseChatItemId: dataId,
customInputs
} = req.body as Props;
await authRequestFromLocal({ req });
if (!customFeedback) {
return res.json({});
}
const feedbackText = replaceVariable(customFeedback, customInputs);
// wait the chat finish
setTimeout(() => {
addCustomFeedbacks({
appId,
chatId,
dataId,
feedbacks: [feedbackText]
});
}, 60000);
if (!chatId || !dataId) {
return res.json({
[NodeOutputKeyEnum.answerText]: `\\n\\n**自动反馈调试**: "${feedbackText}"\\n\\n`,
text: feedbackText
});
}
res.json({
text: feedbackText
});
} catch (err) {
console.log(err);
res.status(500).send(getErrText(err));
}
}

View File

@ -1,45 +0,0 @@
import type { NextApiRequest, NextApiResponse } from 'next';
//@ts-ignore
import type { HttpBodyType } from '@fastgpt/global/core/module/api.d';
import { getErrText } from '@fastgpt/global/common/error/utils';
import { replaceVariable } from '@fastgpt/global/common/string/tools';
import { authRequestFromLocal } from '@fastgpt/service/support/permission/auth/common';
type Props = HttpBodyType<{
text: string;
[key: string]: any;
}>;
export default async function handler(req: NextApiRequest, res: NextApiResponse<any>) {
try {
const {
text,
DYNAMIC_INPUT_KEY: { ...obj }
} = req.body as Props;
await authRequestFromLocal({ req });
// string all value
Object.keys(obj).forEach((key) => {
let val = obj[key];
if (typeof val === 'object') {
val = JSON.stringify(val);
} else if (typeof val === 'number') {
val = String(val);
} else if (typeof val === 'boolean') {
val = val ? 'true' : 'false';
}
obj[key] = val;
});
const textResult = replaceVariable(text, obj);
res.json({
text: textResult
});
} catch (err) {
console.log(err);
res.status(500).send(getErrText(err));
}
}

View File

@ -1,51 +0,0 @@
import type { NextApiResponse } from 'next';
import type { HttpBodyType } from '@fastgpt/global/core/workflow/api.d';
import { getErrText } from '@fastgpt/global/common/error/utils';
import { replaceVariable } from '@fastgpt/global/common/string/tools';
import { authRequestFromLocal } from '@fastgpt/service/support/permission/auth/common';
import { type ApiRequestProps } from '@fastgpt/service/type/next';
type Props = HttpBodyType<{
text: string;
customInputs: Record<string, any>;
}>;
export default async function handler(req: ApiRequestProps<Props>, res: NextApiResponse<any>) {
try {
const { text, customInputs: obj = {} } = req.body;
await authRequestFromLocal({ req });
// string all value
Object.keys(obj).forEach((key) => {
let val = obj[key];
if (typeof val === 'object') {
val = JSON.stringify(val);
} else if (typeof val === 'number') {
val = String(val);
} else if (typeof val === 'boolean') {
val = val ? 'true' : 'false';
}
obj[key] = val;
});
const textResult = replaceVariable(text, obj);
res.json({
text: textResult
});
} catch (err) {
console.log(err);
res.status(500).send(getErrText(err));
}
}
export const config = {
api: {
bodyParser: {
sizeLimit: '16mb'
},
responseLimit: '16mb'
}
};

View File

@ -9,7 +9,6 @@ import {
FlowNodeOutputTypeEnum,
FlowNodeTypeEnum
} from '@fastgpt/global/core/workflow/node/constant';
import { getHandleConfig } from '@fastgpt/global/core/workflow/template/utils';
import type { FlowNodeItemType, StoreNodeItemType } from '@fastgpt/global/core/workflow/type/node';
import type { FlowNodeTemplateType } from '@fastgpt/global/core/workflow/type/node';
import { VARIABLE_NODE_ID } from '@fastgpt/global/core/workflow/constants';
@ -20,7 +19,6 @@ import type {
FlowNodeInputItemType,
FlowNodeOutputItemType
} from '@fastgpt/global/core/workflow/type/io';
import type { PluginTypeEnum } from '@fastgpt/global/core/plugin/constants';
import { getWorkflowGlobalVariables } from './utils';
import type { TFunction } from 'next-i18next';
import type { AppChatConfigType } from '@fastgpt/global/core/app/type';
@ -38,8 +36,8 @@ export const getGlobalVariableNode = ({
id: FlowNodeTypeEnum.globalVariable,
templateType: FlowNodeTemplateTypeEnum.other,
flowNodeType: FlowNodeTypeEnum.emptyNode,
sourceHandle: getHandleConfig(false, false, false, false),
targetHandle: getHandleConfig(false, false, false, false),
showSourceHandle: false,
showTargetHandle: false,
avatar: 'core/workflow/template/variable',
name: t('common:core.module.Variable'),
intro: '',
@ -231,7 +229,6 @@ type V1WorkflowType = {
// runTime field
isEntry?: boolean;
pluginType?: `${PluginTypeEnum}`;
parentId?: string;
};
export const v1Workflow2V2 = (
@ -408,7 +405,6 @@ export const v1Workflow2V2 = (
intro: node.intro,
showStatus: node.showStatus,
pluginId,
pluginType: node.pluginType,
parentId: node.parentId,
version: '481',

View File

@ -0,0 +1,13 @@
export type THelperLine = {
position: number;
nodes: {
left: number;
right: number;
top: number;
bottom: number;
width: number;
height: number;
centerX: number;
centerY: number;
}[];
};

View File

@ -33,9 +33,9 @@ import { type IfElseListItemType } from '@fastgpt/global/core/workflow/template/
import { VariableConditionEnum } from '@fastgpt/global/core/workflow/template/system/ifElse/constant';
import { type AppChatConfigType } from '@fastgpt/global/core/app/type';
import { cloneDeep, isEqual } from 'lodash';
import { getInputComponentProps } from '@fastgpt/global/core/workflow/node/io/utils';
import { workflowSystemVariables } from '../app/utils';
/* ====== node ======= */
export const nodeTemplate2FlowNode = ({
template,
position,
@ -170,6 +170,25 @@ export const storeNode2FlowNode = ({
zIndex
};
};
export const filterSensitiveNodesData = (nodes: StoreNodeItemType[]) => {
const cloneNodes = JSON.parse(JSON.stringify(nodes)) as StoreNodeItemType[];
cloneNodes.forEach((node) => {
// selected dataset
if (node.flowNodeType === FlowNodeTypeEnum.datasetSearchNode) {
node.inputs.forEach((input) => {
if (input.key === NodeInputKeyEnum.datasetSelectList) {
input.value = [];
}
});
}
return node;
});
return cloneNodes;
};
/* ====== edge ======= */
export const storeEdge2RenderEdge = ({ edge }: { edge: StoreEdgeItemType }) => {
const sourceHandle = edge.sourceHandle.replace(/-source-(top|bottom|left)$/, '-source-right');
const targetHandle = edge.targetHandle.replace(/-target-(top|bottom|right)$/, '-target-left');
@ -183,53 +202,24 @@ export const storeEdge2RenderEdge = ({ edge }: { edge: StoreEdgeItemType }) => {
};
};
export const computedNodeInputReference = ({
nodeId,
nodes,
edges,
chatConfig,
t
}: {
nodeId: string;
nodes: FlowNodeItemType[];
edges: Edge[];
chatConfig: AppChatConfigType;
t: TFunction;
}) => {
// get current node
const node = nodes.find((item) => item.nodeId === nodeId);
if (!node) {
return;
}
const parentId = node.parentNodeId;
let sourceNodes: FlowNodeItemType[] = [];
// 根据 edge 获取所有的 source 节点source节点会继续向前递归获取
const findSourceNode = (nodeId: string) => {
const targetEdges = edges.filter((item) => item.target === nodeId || item.target === parentId);
targetEdges.forEach((edge) => {
const sourceNode = nodes.find((item) => item.nodeId === edge.source);
if (!sourceNode) return;
// 去重
if (sourceNodes.some((item) => item.nodeId === sourceNode.nodeId)) {
return;
}
sourceNodes.push(sourceNode);
findSourceNode(sourceNode.nodeId);
});
/* ====== IO ======= */
export const getInputComponentProps = (input: FlowNodeInputItemType) => {
return {
referencePlaceholder: input.referencePlaceholder,
placeholder: input.placeholder,
maxLength: input.maxLength,
list: input.list,
markList: input.markList,
step: input.step,
max: input.max,
min: input.min,
defaultValue: input.defaultValue,
llmModelType: input.llmModelType,
customInputConfig: input.customInputConfig
};
findSourceNode(nodeId);
sourceNodes.push(
getGlobalVariableNode({
nodes,
t,
chatConfig
})
);
return sourceNodes;
};
/* ====== Reference ======= */
export const getRefData = ({
variable,
nodeList,
@ -268,7 +258,6 @@ export const getRefData = ({
required: !!output.required
};
};
// 根据数据类型,过滤无效的节点输出
export const filterWorkflowNodeOutputsByType = (
outputs: FlowNodeOutputItemType[],
@ -337,8 +326,55 @@ export const filterWorkflowNodeOutputsByType = (
validTypeMap[valueType]?.includes(output.valueType)
);
};
export const computedNodeInputReference = ({
nodeId,
nodes,
edges,
chatConfig,
t
}: {
nodeId: string;
nodes: FlowNodeItemType[];
edges: Edge[];
chatConfig: AppChatConfigType;
t: TFunction;
}) => {
// get current node
const node = nodes.find((item) => item.nodeId === nodeId);
if (!node) {
return;
}
const parentId = node.parentNodeId;
let sourceNodes: FlowNodeItemType[] = [];
// 根据 edge 获取所有的 source 节点source节点会继续向前递归获取
const findSourceNode = (nodeId: string) => {
const targetEdges = edges.filter((item) => item.target === nodeId || item.target === parentId);
targetEdges.forEach((edge) => {
const sourceNode = nodes.find((item) => item.nodeId === edge.source);
if (!sourceNode) return;
/* Connection rules */
// 去重
if (sourceNodes.some((item) => item.nodeId === sourceNode.nodeId)) {
return;
}
sourceNodes.push(sourceNode);
findSourceNode(sourceNode.nodeId);
});
};
findSourceNode(nodeId);
sourceNodes.push(
getGlobalVariableNode({
nodes,
t,
chatConfig
})
);
return sourceNodes;
};
/* ====== Connection ======= */
export const checkWorkflowNodeAndConnection = ({
nodes,
edges
@ -481,24 +517,7 @@ export const checkWorkflowNodeAndConnection = ({
}
};
export const filterSensitiveNodesData = (nodes: StoreNodeItemType[]) => {
const cloneNodes = JSON.parse(JSON.stringify(nodes)) as StoreNodeItemType[];
cloneNodes.forEach((node) => {
// selected dataset
if (node.flowNodeType === FlowNodeTypeEnum.datasetSearchNode) {
node.inputs.forEach((input) => {
if (input.key === NodeInputKeyEnum.datasetSelectList) {
input.value = [];
}
});
}
return node;
});
return cloneNodes;
};
/* ====== Variables ======= */
/* get workflowStart output to global variables */
export const getWorkflowGlobalVariables = ({
nodes,
@ -518,47 +537,7 @@ export const getWorkflowGlobalVariables = ({
return [...globalVariables, ...workflowSystemVariables];
};
export type CombinedItemType = Partial<FlowNodeInputItemType> & Partial<FlowNodeOutputItemType>;
/* Reset node to latest version */
export const getLatestNodeTemplate = (
node: FlowNodeItemType,
template: FlowNodeTemplateType
): FlowNodeItemType => {
const updatedNode: FlowNodeItemType = {
...node,
...template,
inputs: template.inputs.map((templateItem) => {
const nodeItem = node.inputs.find((item) => item.key === templateItem.key);
if (nodeItem) {
return {
...templateItem,
value: nodeItem.value,
selectedTypeIndex: nodeItem.selectedTypeIndex,
valueType: nodeItem.valueType
};
}
return { ...templateItem };
}),
outputs: template.outputs.map((templateItem) => {
const nodeItem = node.outputs.find((item) => item.key === templateItem.key);
if (nodeItem) {
return {
...templateItem,
id: nodeItem.id,
value: nodeItem.value,
valueType: nodeItem.valueType
};
}
return { ...templateItem };
}),
name: node.name,
intro: node.intro
};
return updatedNode;
};
/* ====== Snapshot ======= */
export const compareSnapshot = (
snapshot1: {
nodes?: Node[];

View File

@ -17,8 +17,7 @@ import {
nodeTemplate2FlowNode,
storeNode2FlowNode,
filterWorkflowNodeOutputsByType,
checkWorkflowNodeAndConnection,
getLatestNodeTemplate
checkWorkflowNodeAndConnection
} from '@/web/core/workflow/utils';
import type { FlowNodeOutputItemType } from '@fastgpt/global/core/workflow/type/io';
@ -238,102 +237,3 @@ describe('checkWorkflowNodeAndConnection', () => {
expect(result).toBeUndefined();
});
});
describe('getLatestNodeTemplate', () => {
it('should update node to latest template version', () => {
const node: FlowNodeItemType = {
id: 'node1',
nodeId: 'node1',
templateType: 'formInput',
flowNodeType: FlowNodeTypeEnum.formInput,
inputs: [
{
key: 'input1',
value: 'test',
renderTypeList: [FlowNodeInputTypeEnum.input],
label: 'Input 1'
}
],
outputs: [
{
key: 'output1',
value: 'test',
type: FlowNodeOutputTypeEnum.static,
label: 'Output 1',
id: 'output1'
}
],
name: 'Old Name',
intro: 'Old Intro'
};
const template: FlowNodeTemplateType = {
name: 'Template 1',
id: 'template1',
templateType: 'formInput',
flowNodeType: FlowNodeTypeEnum.formInput,
inputs: [
{ key: 'input1', renderTypeList: [FlowNodeInputTypeEnum.input], label: 'Input 1' },
{ key: 'input2', renderTypeList: [FlowNodeInputTypeEnum.input], label: 'Input 2' }
],
outputs: [
{ id: 'output1', key: 'output1', type: FlowNodeOutputTypeEnum.static, label: 'Output 1' },
{ id: 'output2', key: 'output2', type: FlowNodeOutputTypeEnum.static, label: 'Output 2' }
]
};
const result = getLatestNodeTemplate(node, template);
expect(result.inputs).toHaveLength(2);
expect(result.outputs).toHaveLength(2);
expect(result.name).toBe('Old Name');
});
it('should preserve existing values when updating template', () => {
const node: FlowNodeItemType = {
id: 'node1',
nodeId: 'node1',
templateType: 'formInput',
flowNodeType: FlowNodeTypeEnum.formInput,
inputs: [
{
key: 'input1',
value: 'existingValue',
renderTypeList: [FlowNodeInputTypeEnum.input],
label: 'Input 1'
}
],
outputs: [
{
key: 'output1',
value: 'existingOutput',
type: FlowNodeOutputTypeEnum.static,
label: 'Output 1',
id: 'output1'
}
],
name: 'Node Name',
intro: 'Node Intro'
};
const template: FlowNodeTemplateType = {
name: 'Template 1',
id: 'template1',
templateType: 'formInput',
flowNodeType: FlowNodeTypeEnum.formInput,
inputs: [
{ key: 'input1', renderTypeList: [FlowNodeInputTypeEnum.input], label: 'Input 1' },
{ key: 'input2', renderTypeList: [FlowNodeInputTypeEnum.input], label: 'Input 2' }
],
outputs: [
{ id: 'output1', key: 'output1', type: FlowNodeOutputTypeEnum.static, label: 'Output 1' },
{ id: 'output2', key: 'output2', type: FlowNodeOutputTypeEnum.static, label: 'Output 2' }
]
};
const result = getLatestNodeTemplate(node, template);
expect(result.inputs[0].value).toBe('existingValue');
expect(result.outputs[0].value).toBe('existingOutput');
});
});