mirror of
https://github.com/labring/FastGPT.git
synced 2025-10-17 16:45:02 +00:00
feature: V4.11.1 (#5350)
* perf: system toolset & mcp (#5200) * feat: support system toolset * fix: type * fix: system tool config * chore: mcptool config migrate * refactor: mcp toolset * fix: fe type error * fix: type error * fix: show version * chore: support extract tool's secretInputConfig out of inputs * chore: compatible with old version mcp * chore: adjust * deps: update dependency @fastgpt-skd/plugin * fix: version * fix: some bug (#5316) * chore: compatible with old version mcp * fix: version * fix: compatible bug * fix: mcp object params * fix: type error * chore: update test cases * chore: remove log * fix: toolset node name * optimize app logs sort (#5310) * log keys config modal * multiple select * api * fontsize * code * chatid * fix build * fix * fix component * change name * log keys config * fix * delete unused * fix * perf: log code * perf: send auth code modal enter press * fix log (#5328) * perf: mcp toolset comment * perf: log ui * remove log (#5347) * doc * fix: action * remove log * fix: Table Optimization (#5319) * feat: table test: 1 * feat: table test: 2 * feat: table test: 3 * feat: table test: 4 * feat: table test : 5 把maxSize改回chunkSize * feat: table test : 6 都删了,只看maxSize * feat: table test : 7 恢复初始,接下来删除标签功能 * feat: table test : 8 删除标签功能 * feat: table test : 9 删除标签功能成功 * feat: table test : 10 继续调试,修改trainingStates * feat: table test : 11 修改第一步 * feat: table test : 12 修改第二步 * feat: table test : 13 修改了HtmlTable2Md * feat: table test : 14 修改表头分块规则 * feat: table test : 15 前面表格分的太细了 * feat: table test : 16 改着改着表头又不加了 * feat: table test : 17 用CUSTOM_SPLIT_SIGN不行,重新改 * feat: table test : 18 表头仍然还会多加,但现在分块搞的合理了终于 * feat: table test : 19 还是需要搞好表头问题,先保存一下调试情况 * feat: table test : 20 调试结束,看一下replace有没有问题,没问题就pr * feat: table test : 21 先把注释删了 * feat: table test : 21 注释replace都改了,下面切main分支看看情况 * feat: table test : 22 修改旧文件 * feat: table test : 23 修改测试文件 * feat: table test : 24 xlsx表格处理 * feat: table test : 25 刚才没保存先com了 * feat: table test : 26 fix * feat: table test : 27 先com一版调试 * feat: table test : 28 试试放format2csv里 * feat: table test : 29 xlsx解决 * feat: table test : 30 tablesplit解决 * feat: table test : 31 * feat: table test : 32 * perf: table split * perf: mcp old version compatibility (#5342) * fix: system-tool secret inputs * fix: rewrite runtime node i18n for system tool * perf: mcp old version compatibility * fix: splitPluginId * fix: old mcp toolId * fix: filter secret key * feat: support system toolset activation * chore: remove log * perf: mcp update * perf: rewrite toolset * fix:delete variable id (#5335) * perf: variable update * fix: multiple select ui * perf: model config move to plugin * fix: var conflit * perf: variable checker * Avoid empty number * update doc time * fix: test * fix: mcp object * update count app * update count app --------- Co-authored-by: Finley Ge <32237950+FinleyGe@users.noreply.github.com> Co-authored-by: heheer <heheer@sealos.io> Co-authored-by: heheer <zhiyu44@qq.com> Co-authored-by: colnii <1286949794@qq.com> Co-authored-by: dreamer6680 <1468683855@qq.com>
This commit is contained in:
@@ -56,12 +56,12 @@ const getNodeInputRenderTypeFromSchemaInputType = ({
|
||||
}
|
||||
if (type === 'string') {
|
||||
return {
|
||||
renderTypeList: [FlowNodeInputTypeEnum.input]
|
||||
renderTypeList: [FlowNodeInputTypeEnum.input, FlowNodeInputTypeEnum.reference]
|
||||
};
|
||||
}
|
||||
if (type === 'number') {
|
||||
return {
|
||||
renderTypeList: [FlowNodeInputTypeEnum.numberInput],
|
||||
renderTypeList: [FlowNodeInputTypeEnum.numberInput, FlowNodeInputTypeEnum.reference],
|
||||
max: maximum,
|
||||
min: minimum
|
||||
};
|
||||
@@ -71,7 +71,7 @@ const getNodeInputRenderTypeFromSchemaInputType = ({
|
||||
renderTypeList: [FlowNodeInputTypeEnum.switch]
|
||||
};
|
||||
}
|
||||
return { renderTypeList: [FlowNodeInputTypeEnum.JSONEditor] };
|
||||
return { renderTypeList: [FlowNodeInputTypeEnum.JSONEditor, FlowNodeInputTypeEnum.reference] };
|
||||
};
|
||||
export const jsonSchema2NodeInput = (jsonSchema: JSONSchemaInputType): FlowNodeInputItemType[] => {
|
||||
return Object.entries(jsonSchema?.properties || {}).map(([key, value]) => ({
|
||||
|
49
packages/global/core/app/logs/constants.ts
Normal file
49
packages/global/core/app/logs/constants.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { i18nT } from '../../../../web/i18n/utils';
|
||||
|
||||
export enum AppLogKeysEnum {
|
||||
SOURCE = 'source',
|
||||
USER = 'user',
|
||||
TITLE = 'title',
|
||||
SESSION_ID = 'sessionId',
|
||||
CREATED_TIME = 'createdTime',
|
||||
LAST_CONVERSATION_TIME = 'lastConversationTime',
|
||||
MESSAGE_COUNT = 'messageCount',
|
||||
FEEDBACK = 'feedback',
|
||||
CUSTOM_FEEDBACK = 'customFeedback',
|
||||
ANNOTATED_COUNT = 'annotatedCount',
|
||||
POINTS = 'points',
|
||||
RESPONSE_TIME = 'responseTime',
|
||||
ERROR_COUNT = 'errorCount'
|
||||
}
|
||||
|
||||
export const AppLogKeysEnumMap = {
|
||||
[AppLogKeysEnum.SOURCE]: i18nT('app:logs_keys_source'),
|
||||
[AppLogKeysEnum.USER]: i18nT('app:logs_keys_user'),
|
||||
[AppLogKeysEnum.TITLE]: i18nT('app:logs_keys_title'),
|
||||
[AppLogKeysEnum.SESSION_ID]: i18nT('app:logs_keys_sessionId'),
|
||||
[AppLogKeysEnum.CREATED_TIME]: i18nT('app:logs_keys_createdTime'),
|
||||
[AppLogKeysEnum.LAST_CONVERSATION_TIME]: i18nT('app:logs_keys_lastConversationTime'),
|
||||
[AppLogKeysEnum.MESSAGE_COUNT]: i18nT('app:logs_keys_messageCount'),
|
||||
[AppLogKeysEnum.FEEDBACK]: i18nT('app:logs_keys_feedback'),
|
||||
[AppLogKeysEnum.CUSTOM_FEEDBACK]: i18nT('app:logs_keys_customFeedback'),
|
||||
[AppLogKeysEnum.ANNOTATED_COUNT]: i18nT('app:logs_keys_annotatedCount'),
|
||||
[AppLogKeysEnum.POINTS]: i18nT('app:logs_keys_points'),
|
||||
[AppLogKeysEnum.RESPONSE_TIME]: i18nT('app:logs_keys_responseTime'),
|
||||
[AppLogKeysEnum.ERROR_COUNT]: i18nT('app:logs_keys_errorCount')
|
||||
};
|
||||
|
||||
export const DefaultAppLogKeys = [
|
||||
{ key: AppLogKeysEnum.SOURCE, enable: true },
|
||||
{ key: AppLogKeysEnum.USER, enable: true },
|
||||
{ key: AppLogKeysEnum.TITLE, enable: true },
|
||||
{ key: AppLogKeysEnum.SESSION_ID, enable: false },
|
||||
{ key: AppLogKeysEnum.CREATED_TIME, enable: false },
|
||||
{ key: AppLogKeysEnum.LAST_CONVERSATION_TIME, enable: true },
|
||||
{ key: AppLogKeysEnum.MESSAGE_COUNT, enable: true },
|
||||
{ key: AppLogKeysEnum.FEEDBACK, enable: true },
|
||||
{ key: AppLogKeysEnum.CUSTOM_FEEDBACK, enable: false },
|
||||
{ key: AppLogKeysEnum.ANNOTATED_COUNT, enable: false },
|
||||
{ key: AppLogKeysEnum.POINTS, enable: false },
|
||||
{ key: AppLogKeysEnum.RESPONSE_TIME, enable: false },
|
||||
{ key: AppLogKeysEnum.ERROR_COUNT, enable: false }
|
||||
];
|
12
packages/global/core/app/logs/type.d.ts
vendored
Normal file
12
packages/global/core/app/logs/type.d.ts
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import type { AppLogKeysEnum } from './constants';
|
||||
|
||||
export type AppLogKeysType = {
|
||||
key: AppLogKeysEnum;
|
||||
enable: boolean;
|
||||
};
|
||||
|
||||
export type AppLogKeysSchemaType = {
|
||||
teamId: string;
|
||||
appId: string;
|
||||
logKeys: AppLogKeysType[];
|
||||
};
|
@@ -14,38 +14,37 @@ import { type RuntimeNodeItemType } from '../../workflow/runtime/type';
|
||||
import { type StoreSecretValueType } from '../../../common/secret/type';
|
||||
import { jsonSchema2NodeInput } from '../jsonschema';
|
||||
import { getNanoid } from '../../../common/string/tools';
|
||||
import { PluginSourceEnum } from '../plugin/constants';
|
||||
|
||||
export const getMCPToolSetRuntimeNode = ({
|
||||
url,
|
||||
toolList,
|
||||
headerSecret,
|
||||
name,
|
||||
avatar
|
||||
avatar,
|
||||
toolId
|
||||
}: {
|
||||
url: string;
|
||||
toolList: McpToolConfigType[];
|
||||
headerSecret?: StoreSecretValueType;
|
||||
name?: string;
|
||||
avatar?: string;
|
||||
toolId: string;
|
||||
}): RuntimeNodeItemType => {
|
||||
return {
|
||||
nodeId: getNanoid(16),
|
||||
flowNodeType: FlowNodeTypeEnum.toolSet,
|
||||
avatar,
|
||||
intro: '',
|
||||
inputs: [
|
||||
{
|
||||
key: NodeInputKeyEnum.toolSetData,
|
||||
label: '',
|
||||
valueType: WorkflowIOValueTypeEnum.object,
|
||||
renderTypeList: [FlowNodeInputTypeEnum.hidden],
|
||||
value: {
|
||||
url,
|
||||
headerSecret,
|
||||
toolList
|
||||
}
|
||||
intro: 'MCP Tools',
|
||||
toolConfig: {
|
||||
mcpToolSet: {
|
||||
toolList,
|
||||
headerSecret,
|
||||
url,
|
||||
toolId
|
||||
}
|
||||
],
|
||||
},
|
||||
inputs: [],
|
||||
outputs: [],
|
||||
name: name || '',
|
||||
version: ''
|
||||
@@ -54,34 +53,24 @@ export const getMCPToolSetRuntimeNode = ({
|
||||
|
||||
export const getMCPToolRuntimeNode = ({
|
||||
tool,
|
||||
url,
|
||||
headerSecret,
|
||||
avatar = 'core/app/type/mcpToolsFill'
|
||||
avatar = 'core/app/type/mcpToolsFill',
|
||||
parentId
|
||||
}: {
|
||||
tool: McpToolConfigType;
|
||||
url: string;
|
||||
headerSecret?: StoreSecretValueType;
|
||||
avatar?: string;
|
||||
parentId: string;
|
||||
}): RuntimeNodeItemType => {
|
||||
return {
|
||||
nodeId: getNanoid(16),
|
||||
flowNodeType: FlowNodeTypeEnum.tool,
|
||||
avatar,
|
||||
intro: tool.description,
|
||||
inputs: [
|
||||
{
|
||||
key: NodeInputKeyEnum.toolData,
|
||||
label: 'Tool Data',
|
||||
valueType: WorkflowIOValueTypeEnum.object,
|
||||
renderTypeList: [FlowNodeInputTypeEnum.hidden],
|
||||
value: {
|
||||
...tool,
|
||||
url,
|
||||
headerSecret
|
||||
}
|
||||
},
|
||||
...jsonSchema2NodeInput(tool.inputSchema)
|
||||
],
|
||||
toolConfig: {
|
||||
mcpTool: {
|
||||
toolId: `${PluginSourceEnum.mcp}-${parentId}/${tool.name}`
|
||||
}
|
||||
},
|
||||
inputs: jsonSchema2NodeInput(tool.inputSchema),
|
||||
outputs: [
|
||||
{
|
||||
id: NodeOutputKeyEnum.rawResponse,
|
||||
@@ -97,3 +86,12 @@ export const getMCPToolRuntimeNode = ({
|
||||
version: ''
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the parent id of the mcp toolset
|
||||
* mcp-123123/toolName ==> 123123
|
||||
* 123123/toolName ==> 123123
|
||||
* @param id mcp-parentId/name or parentId/name
|
||||
* @returns parentId
|
||||
*/
|
||||
export const getMCPParentId = (id: string) => id.split('-').pop()?.split('/')[0];
|
||||
|
@@ -2,6 +2,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
|
||||
mcp = 'mcp', // mcp
|
||||
// @deprecated
|
||||
community = 'community' // this is deprecated, will be replaced by systemTool
|
||||
}
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import { type StoreNodeItemType } from '../../workflow/type/node';
|
||||
import { type FlowNodeInputItemType } from '../../workflow/type/io';
|
||||
import { FlowNodeTypeEnum } from '../../workflow/node/constant';
|
||||
import { PluginSourceEnum } from './constants';
|
||||
|
||||
export const getPluginInputsFromStoreNodes = (nodes: StoreNodeItemType[]) => {
|
||||
return nodes.find((node) => node.flowNodeType === FlowNodeTypeEnum.pluginInput)?.inputs || [];
|
||||
@@ -22,3 +23,42 @@ export const getPluginRunContent = ({
|
||||
});
|
||||
return JSON.stringify(pluginInputsWithValue);
|
||||
};
|
||||
|
||||
/**
|
||||
plugin id rule:
|
||||
- personal: ObjectId
|
||||
- commercial: commercial-ObjectId
|
||||
- systemtool: systemTool-id
|
||||
- mcp tool: mcp-parentId/toolName
|
||||
(deprecated) community: community-id
|
||||
*/
|
||||
export function splitCombinePluginId(id: string) {
|
||||
const splitRes = id.split('-');
|
||||
if (splitRes.length === 1) {
|
||||
// app id
|
||||
return {
|
||||
source: PluginSourceEnum.personal,
|
||||
pluginId: id
|
||||
};
|
||||
}
|
||||
|
||||
const [source, ...rest] = id.split('-') as [PluginSourceEnum, string | undefined];
|
||||
const pluginId = rest.join('-');
|
||||
if (!source || !pluginId) throw new Error('pluginId not found');
|
||||
|
||||
// 兼容4.10.0 之前的插件
|
||||
if (source === 'community' || id === 'commercial-dalle3') {
|
||||
return {
|
||||
source: PluginSourceEnum.systemTool,
|
||||
pluginId: `${PluginSourceEnum.systemTool}-${pluginId}`
|
||||
};
|
||||
}
|
||||
|
||||
if (source === 'mcp') {
|
||||
return {
|
||||
source: PluginSourceEnum.mcp,
|
||||
pluginId
|
||||
};
|
||||
}
|
||||
return { source, pluginId: id };
|
||||
}
|
||||
|
4
packages/global/core/app/type.d.ts
vendored
4
packages/global/core/app/type.d.ts
vendored
@@ -146,7 +146,7 @@ export type SettingAIDataType = {
|
||||
|
||||
// variable
|
||||
export type VariableItemType = {
|
||||
id: string;
|
||||
// id: string;
|
||||
key: string;
|
||||
label: string;
|
||||
type: VariableInputEnum;
|
||||
@@ -161,6 +161,8 @@ export type VariableItemType = {
|
||||
max?: number;
|
||||
min?: number;
|
||||
// select
|
||||
list?: { label: string; value: string }[];
|
||||
// @deprecated
|
||||
enums?: { value: string; label: string }[];
|
||||
};
|
||||
// tts
|
||||
|
@@ -105,6 +105,13 @@ export const toolValueTypeList: {
|
||||
type: 'boolean'
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
label: 'object',
|
||||
value: WorkflowIOValueTypeEnum.object,
|
||||
jsonSchema: {
|
||||
type: 'object'
|
||||
}
|
||||
}
|
||||
];
|
||||
export const valueTypeJsonSchemaMap: Record<string, JsonSchemaPropertiesItemType> =
|
||||
|
@@ -87,6 +87,7 @@ export const valueTypeFormat = (value: any, type?: WorkflowIOValueTypeEnum) => {
|
||||
return typeof value === 'object' ? JSON.stringify(value) : String(value);
|
||||
}
|
||||
if (type === WorkflowIOValueTypeEnum.number) {
|
||||
if (value === '') return undefined;
|
||||
return Number(value);
|
||||
}
|
||||
if (type === WorkflowIOValueTypeEnum.boolean) {
|
||||
|
17
packages/global/core/workflow/type/node.d.ts
vendored
17
packages/global/core/workflow/type/node.d.ts
vendored
@@ -23,14 +23,29 @@ import type { AppDetailType, AppSchema, McpToolConfigType } from '../../app/type
|
||||
import type { ParentIdType } from 'common/parentFolder/type';
|
||||
import { AppTypeEnum } from '../../app/constants';
|
||||
import type { WorkflowInteractiveResponseType } from '../template/system/interactive/type';
|
||||
import type { StoreSecretValueType } from '../../../common/secret/type';
|
||||
|
||||
export type NodeToolConfigType = {
|
||||
mcpTool?: McpToolConfigType & {
|
||||
mcpToolSet?: {
|
||||
toolId: string; // ObjectId of the MCP App
|
||||
url: string;
|
||||
headerSecret?: StoreSecretValueType;
|
||||
toolList: McpToolConfigType[];
|
||||
};
|
||||
mcpTool?: {
|
||||
toolId: string;
|
||||
};
|
||||
systemTool?: {
|
||||
toolId: string;
|
||||
};
|
||||
systemToolSet?: {
|
||||
toolId: string;
|
||||
toolList: {
|
||||
toolId: string;
|
||||
name: string;
|
||||
description: string;
|
||||
}[];
|
||||
};
|
||||
};
|
||||
|
||||
export type FlowNodeCommonType = {
|
||||
|
@@ -18,6 +18,7 @@ import {
|
||||
type ReferenceArrayValueType,
|
||||
type ReferenceItemValueType
|
||||
} from './type/io.d';
|
||||
import type { NodeToolConfigType } from './type/node';
|
||||
import { type StoreNodeItemType } from './type/node';
|
||||
import type {
|
||||
VariableItemType,
|
||||
@@ -310,35 +311,25 @@ export const appData2FlowNodeIO = ({
|
||||
};
|
||||
};
|
||||
|
||||
export const toolData2FlowNodeIO = ({
|
||||
nodes
|
||||
}: {
|
||||
nodes: StoreNodeItemType[];
|
||||
}): {
|
||||
inputs: FlowNodeInputItemType[];
|
||||
outputs: FlowNodeOutputItemType[];
|
||||
} => {
|
||||
export const toolData2FlowNodeIO = ({ nodes }: { nodes: StoreNodeItemType[] }) => {
|
||||
const toolNode = nodes.find((node) => node.flowNodeType === FlowNodeTypeEnum.tool);
|
||||
|
||||
return {
|
||||
inputs: toolNode?.inputs || [],
|
||||
outputs: toolNode?.outputs || []
|
||||
outputs: toolNode?.outputs || [],
|
||||
toolConfig: toolNode?.toolConfig
|
||||
};
|
||||
};
|
||||
|
||||
export const toolSetData2FlowNodeIO = ({
|
||||
nodes
|
||||
}: {
|
||||
nodes: StoreNodeItemType[];
|
||||
}): {
|
||||
inputs: FlowNodeInputItemType[];
|
||||
outputs: FlowNodeOutputItemType[];
|
||||
} => {
|
||||
export const toolSetData2FlowNodeIO = ({ nodes }: { nodes: StoreNodeItemType[] }) => {
|
||||
const toolSetNode = nodes.find((node) => node.flowNodeType === FlowNodeTypeEnum.toolSet);
|
||||
|
||||
return {
|
||||
inputs: toolSetNode?.inputs || [],
|
||||
outputs: toolSetNode?.outputs || []
|
||||
outputs: toolSetNode?.outputs || [],
|
||||
toolConfig: toolSetNode?.toolConfig,
|
||||
showSourceHandle: false,
|
||||
showTargetHandle: false
|
||||
};
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user