|<\/td>/g, '').trim();
-
+ let content = '';
+ if (cell.endsWith('/>')) {
+ content = '';
+ } else {
+ content = cell.replace(/]*>|<\/td>/g, '').trim();
+ }
for (let i = 0; i < rowspan; i++) {
for (let j = 0; j < colspan; j++) {
if (!tableData[rowIndex + i]) {
diff --git a/packages/global/common/string/textSplitter.ts b/packages/global/common/string/textSplitter.ts
index 6ded96260..0ac3971e3 100644
--- a/packages/global/common/string/textSplitter.ts
+++ b/packages/global/common/string/textSplitter.ts
@@ -64,7 +64,15 @@ const strIsMdTable = (str: string) => {
};
const markdownTableSplit = (props: SplitProps): SplitResponse => {
let { text = '', chunkSize } = props;
- const splitText2Lines = text.split('\n');
+
+ // split by rows
+ const splitText2Lines = text.split('\n').filter((line) => line.trim());
+
+ // If there are not enough rows to form a table, return directly
+ if (splitText2Lines.length < 2) {
+ return { chunks: [text], chars: text.length };
+ }
+
const header = splitText2Lines[0];
const headerSize = header.split('|').length - 2;
@@ -130,21 +138,6 @@ const commonSplit = (props: SplitProps): SplitResponse => {
text = text.replace(/(```[\s\S]*?```|~~~[\s\S]*?~~~)/g, function (match) {
return match.replace(/\n/g, codeBlockMarker);
});
- // 2. Markdown 表格处理 - 单独提取表格出来,进行表头合并
- const tableReg =
- /(\n\|(?:(?:[^\n|]+\|){1,})\n\|(?:[:\-\s]+\|){1,}\n(?:\|(?:[^\n|]+\|)*\n?)*)(?:\n|$)/g;
- const tableDataList = text.match(tableReg);
- if (tableDataList) {
- tableDataList.forEach((tableData) => {
- const { chunks } = markdownTableSplit({
- text: tableData.trim(),
- chunkSize
- });
-
- const splitText = chunks.join('\n');
- text = text.replace(tableData, `\n${splitText}\n`);
- });
- }
// replace invalid \n
text = text.replace(/(\r?\n|\r){3,}/g, '\n\n\n');
@@ -173,7 +166,7 @@ const commonSplit = (props: SplitProps): SplitResponse => {
const stepReges: { reg: RegExp | string; maxLen: number }[] = [
...customReg.map((text) => ({
- reg: text.replaceAll('\\n', '\n'),
+ reg: text.replace(/\\n/g, '\n'),
maxLen: chunkSize
})),
...markdownHeaderRules,
@@ -181,7 +174,7 @@ const commonSplit = (props: SplitProps): SplitResponse => {
{ reg: /([\n](```[\s\S]*?```|~~~[\s\S]*?~~~))/g, maxLen: maxSize }, // code block
// HTML Table tag 尽可能保障完整
{
- reg: /(\n\|(?:(?:[^\n|]+\|){1,})\n\|(?:[:\-\s]+\|){1,}\n(?:\|(?:[^\n|]+\|)*\n)*)/g,
+ reg: /(\n\|(?:[^\n|]*\|)+\n\|(?:[:\-\s]*\|)+\n(?:\|(?:[^\n|]*\|)*\n)*)/g,
maxLen: chunkSize
}, // Markdown Table 尽可能保证完整性
{ reg: /(\n{2,})/g, maxLen: chunkSize },
@@ -332,6 +325,21 @@ const commonSplit = (props: SplitProps): SplitResponse => {
const newText = lastText + currentText;
const newTextLen = getTextValidLength(newText);
+ // split the current table if it will exceed after adding
+ if (strIsMdTable(currentText) && newTextLen > maxLen) {
+ if (lastTextLen > 0) {
+ chunks.push(lastText);
+ lastText = '';
+ }
+
+ const { chunks: tableChunks } = markdownTableSplit({
+ text: currentText,
+ chunkSize: chunkSize * 1.2
+ });
+
+ chunks.push(...tableChunks);
+ continue;
+ }
// Markdown 模式下,会强制向下拆分最小块,并再最后一个标题深度,给小块都补充上所有标题(包含父级标题)
if (isMarkdownStep) {
// split new Text, split chunks must will greater 1 (small lastText)
@@ -468,10 +476,10 @@ export const splitText2Chunks = (props: SplitProps): SplitResponse => {
const splitResult = splitWithCustomSign.map((item) => {
if (strIsMdTable(item)) {
- return markdownTableSplit(props);
+ return markdownTableSplit({ ...props, text: item });
}
- return commonSplit(props);
+ return commonSplit({ ...props, text: item });
});
return {
diff --git a/packages/global/common/string/time.ts b/packages/global/common/string/time.ts
index 0689803f5..93037fd77 100644
--- a/packages/global/common/string/time.ts
+++ b/packages/global/common/string/time.ts
@@ -96,7 +96,7 @@ export const getNextTimeByCronStringAndTimezone = ({
tz: timezone
};
const interval = cronParser.parseExpression(cronString, options);
- const date = interval.next().toString();
+ const date = String(interval.next());
return new Date(date);
} catch (error) {
diff --git a/packages/global/core/app/jsonschema.ts b/packages/global/core/app/jsonschema.ts
index 43326d909..ac28f7367 100644
--- a/packages/global/core/app/jsonschema.ts
+++ b/packages/global/core/app/jsonschema.ts
@@ -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]) => ({
diff --git a/packages/global/core/app/logs/constants.ts b/packages/global/core/app/logs/constants.ts
new file mode 100644
index 000000000..cc8122080
--- /dev/null
+++ b/packages/global/core/app/logs/constants.ts
@@ -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 }
+];
diff --git a/packages/global/core/app/logs/type.d.ts b/packages/global/core/app/logs/type.d.ts
new file mode 100644
index 000000000..84e198d9f
--- /dev/null
+++ b/packages/global/core/app/logs/type.d.ts
@@ -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[];
+};
diff --git a/packages/global/core/app/mcpTools/utils.ts b/packages/global/core/app/mcpTools/utils.ts
index 9f60e43c9..d9374a7ae 100644
--- a/packages/global/core/app/mcpTools/utils.ts
+++ b/packages/global/core/app/mcpTools/utils.ts
@@ -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];
diff --git a/packages/global/core/app/plugin/constants.ts b/packages/global/core/app/plugin/constants.ts
index 60b0df4af..56f44a0db 100644
--- a/packages/global/core/app/plugin/constants.ts
+++ b/packages/global/core/app/plugin/constants.ts
@@ -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
}
diff --git a/packages/global/core/app/plugin/utils.ts b/packages/global/core/app/plugin/utils.ts
index e2e016b87..8b6088639 100644
--- a/packages/global/core/app/plugin/utils.ts
+++ b/packages/global/core/app/plugin/utils.ts
@@ -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 };
+}
diff --git a/packages/global/core/app/type.d.ts b/packages/global/core/app/type.d.ts
index 8e4c86a94..a3514d883 100644
--- a/packages/global/core/app/type.d.ts
+++ b/packages/global/core/app/type.d.ts
@@ -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
diff --git a/packages/global/core/workflow/constants.ts b/packages/global/core/workflow/constants.ts
index 533e2e776..1cb29ffb6 100644
--- a/packages/global/core/workflow/constants.ts
+++ b/packages/global/core/workflow/constants.ts
@@ -105,6 +105,13 @@ export const toolValueTypeList: {
type: 'boolean'
}
}
+ },
+ {
+ label: 'object',
+ value: WorkflowIOValueTypeEnum.object,
+ jsonSchema: {
+ type: 'object'
+ }
}
];
export const valueTypeJsonSchemaMap: Record =
diff --git a/packages/global/core/workflow/runtime/utils.ts b/packages/global/core/workflow/runtime/utils.ts
index 1fe272ce5..7fcae94c1 100644
--- a/packages/global/core/workflow/runtime/utils.ts
+++ b/packages/global/core/workflow/runtime/utils.ts
@@ -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) {
diff --git a/packages/global/core/workflow/type/node.d.ts b/packages/global/core/workflow/type/node.d.ts
index d04cbca67..1da7ad002 100644
--- a/packages/global/core/workflow/type/node.d.ts
+++ b/packages/global/core/workflow/type/node.d.ts
@@ -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 = {
diff --git a/packages/global/core/workflow/utils.ts b/packages/global/core/workflow/utils.ts
index 15f63d52a..070f29ea7 100644
--- a/packages/global/core/workflow/utils.ts
+++ b/packages/global/core/workflow/utils.ts
@@ -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
};
};
diff --git a/packages/service/core/ai/config/provider/AliCloud.json b/packages/service/core/ai/config/provider/AliCloud.json
deleted file mode 100644
index 64a175c56..000000000
--- a/packages/service/core/ai/config/provider/AliCloud.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "provider": "AliCloud",
- "list": [
- {
- "model": "SenseVoiceSmall",
- "name": "SenseVoiceSmall",
- "type": "stt"
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/BAAI.json b/packages/service/core/ai/config/provider/BAAI.json
deleted file mode 100644
index 86237c654..000000000
--- a/packages/service/core/ai/config/provider/BAAI.json
+++ /dev/null
@@ -1,17 +0,0 @@
-{
- "provider": "BAAI",
- "list": [
- {
- "model": "bge-m3",
- "name": "bge-m3",
- "defaultToken": 512,
- "maxToken": 8000,
- "type": "embedding"
- },
- {
- "model": "bge-reranker-v2-m3",
- "name": "bge-reranker-v2-m3",
- "type": "rerank"
- }
- ]
-}
\ No newline at end of file
diff --git a/packages/service/core/ai/config/provider/Baichuan.json b/packages/service/core/ai/config/provider/Baichuan.json
deleted file mode 100644
index e5599e5c6..000000000
--- a/packages/service/core/ai/config/provider/Baichuan.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "provider": "Baichuan",
- "list": []
-}
\ No newline at end of file
diff --git a/packages/service/core/ai/config/provider/ChatGLM.json b/packages/service/core/ai/config/provider/ChatGLM.json
deleted file mode 100644
index 49bbaa293..000000000
--- a/packages/service/core/ai/config/provider/ChatGLM.json
+++ /dev/null
@@ -1,121 +0,0 @@
-{
- "provider": "ChatGLM",
- "list": [
- {
- "model": "glm-4-air",
- "name": "glm-4-air",
- "maxContext": 128000,
- "maxResponse": 4000,
- "quoteMaxToken": 120000,
- "maxTemperature": 0.99,
- "showTopP": true,
- "responseFormatList": ["text", "json_object"],
- "showStopSign": true,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "glm-4-flash",
- "name": "glm-4-flash",
- "maxContext": 128000,
- "maxResponse": 4000,
- "quoteMaxToken": 120000,
- "maxTemperature": 0.99,
- "showTopP": true,
- "responseFormatList": ["text", "json_object"],
- "showStopSign": true,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "glm-4-long",
- "name": "glm-4-long",
- "maxContext": 1000000,
- "maxResponse": 4000,
- "quoteMaxToken": 900000,
- "maxTemperature": 0.99,
- "showTopP": true,
- "responseFormatList": ["text", "json_object"],
- "showStopSign": true,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "glm-4-plus",
- "name": "GLM-4-plus",
- "maxContext": 128000,
- "maxResponse": 4000,
- "quoteMaxToken": 120000,
- "maxTemperature": 0.99,
- "showTopP": true,
- "responseFormatList": ["text", "json_object"],
- "showStopSign": true,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "glm-4v-flash",
- "name": "glm-4v-flash",
- "maxContext": 8000,
- "maxResponse": 1000,
- "quoteMaxToken": 6000,
- "maxTemperature": 0.99,
- "showTopP": true,
- "showStopSign": true,
- "vision": true,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "glm-4v-plus",
- "name": "GLM-4v-plus",
- "maxContext": 8000,
- "maxResponse": 1000,
- "quoteMaxToken": 6000,
- "maxTemperature": 0.99,
- "showTopP": true,
- "showStopSign": true,
- "vision": true,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "embedding-3",
- "name": "embedding-3",
- "defaultToken": 512,
- "maxToken": 8000,
- "defaultConfig": {
- "dimensions": 1024
- },
- "type": "embedding"
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/Claude.json b/packages/service/core/ai/config/provider/Claude.json
deleted file mode 100644
index 6a9d8e18a..000000000
--- a/packages/service/core/ai/config/provider/Claude.json
+++ /dev/null
@@ -1,124 +0,0 @@
-{
- "provider": "Claude",
- "list": [
- {
- "model": "claude-sonnet-4-20250514",
- "name": "claude-sonnet-4-20250514",
- "maxContext": 200000,
- "maxResponse": 8000,
- "quoteMaxToken": 100000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "claude-opus-4-20250514",
- "name": "claude-opus-4-20250514",
- "maxContext": 200000,
- "maxResponse": 4096,
- "quoteMaxToken": 100000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "claude-3-7-sonnet-20250219",
- "name": "claude-3-7-sonnet-20250219",
- "maxContext": 200000,
- "maxResponse": 8000,
- "quoteMaxToken": 100000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "claude-3-5-haiku-20241022",
- "name": "claude-3-5-haiku-20241022",
- "maxContext": 200000,
- "maxResponse": 8000,
- "quoteMaxToken": 100000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "claude-3-5-sonnet-20240620",
- "name": "Claude-3-5-sonnet-20240620",
- "maxContext": 200000,
- "maxResponse": 8000,
- "quoteMaxToken": 100000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "claude-3-5-sonnet-20241022",
- "name": "Claude-3-5-sonnet-20241022",
- "maxContext": 200000,
- "maxResponse": 8000,
- "quoteMaxToken": 100000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "claude-3-opus-20240229",
- "name": "claude-3-opus-20240229",
- "maxContext": 200000,
- "maxResponse": 4096,
- "quoteMaxToken": 100000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/DeepSeek.json b/packages/service/core/ai/config/provider/DeepSeek.json
deleted file mode 100644
index b53789b08..000000000
--- a/packages/service/core/ai/config/provider/DeepSeek.json
+++ /dev/null
@@ -1,39 +0,0 @@
-{
- "provider": "DeepSeek",
- "list": [
- {
- "model": "deepseek-chat",
- "name": "Deepseek-chat",
- "maxContext": 64000,
- "maxResponse": 8000,
- "quoteMaxToken": 60000,
- "maxTemperature": 1,
- "showTopP": true,
- "responseFormatList": ["text", "json_object"],
- "showStopSign": true,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "type": "llm"
- },
- {
- "model": "deepseek-reasoner",
- "name": "Deepseek-reasoner",
- "maxContext": 64000,
- "maxResponse": 8000,
- "quoteMaxToken": 60000,
- "maxTemperature": null,
- "vision": false,
- "reasoning": true,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": false,
- "showStopSign": false
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/Doubao.json b/packages/service/core/ai/config/provider/Doubao.json
deleted file mode 100644
index 759a392b6..000000000
--- a/packages/service/core/ai/config/provider/Doubao.json
+++ /dev/null
@@ -1,276 +0,0 @@
-{
- "provider": "Doubao",
- "list": [
- {
- "model": "doubao-seed-1-6-250615",
- "name": "doubao-seed-1-6-250615",
- "maxContext": 220000,
- "maxResponse": 16000,
- "quoteMaxToken": 220000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "doubao-seed-1-6-flash-250615",
- "name": "doubao-seed-1-6-flash-250615",
- "maxContext": 220000,
- "maxResponse": 16000,
- "quoteMaxToken": 220000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "doubao-seed-1-6-thinking-250615",
- "name": "doubao-seed-1-6-thinking-250615",
- "maxContext": 220000,
- "maxResponse": 16000,
- "quoteMaxToken": 220000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "Doubao-1.5-lite-32k",
- "name": "Doubao-1.5-lite-32k",
- "maxContext": 32000,
- "maxResponse": 4000,
- "quoteMaxToken": 32000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "Doubao-1.5-pro-32k",
- "name": "Doubao-1.5-pro-32k",
- "maxContext": 32000,
- "maxResponse": 4000,
- "quoteMaxToken": 32000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "Doubao-1.5-pro-256k",
- "name": "Doubao-1.5-pro-256k",
- "maxContext": 256000,
- "maxResponse": 12000,
- "quoteMaxToken": 256000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "Doubao-1.5-vision-pro-32k",
- "name": "Doubao-1.5-vision-pro-32k",
- "maxContext": 32000,
- "maxResponse": 4000,
- "quoteMaxToken": 32000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "Doubao-lite-4k",
- "name": "Doubao-lite-4k",
- "maxContext": 4000,
- "maxResponse": 4000,
- "quoteMaxToken": 4000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "Doubao-lite-32k",
- "name": "Doubao-lite-32k",
- "maxContext": 32000,
- "maxResponse": 4000,
- "quoteMaxToken": 32000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "Doubao-lite-128k",
- "name": "Doubao-lite-128k",
- "maxContext": 128000,
- "maxResponse": 4000,
- "quoteMaxToken": 120000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "Doubao-vision-lite-32k",
- "name": "Doubao-vision-lite-32k",
- "maxContext": 32000,
- "maxResponse": 4000,
- "quoteMaxToken": 32000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "Doubao-pro-4k",
- "name": "Doubao-pro-4k",
- "maxContext": 4000,
- "maxResponse": 4000,
- "quoteMaxToken": 4000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "Doubao-pro-32k",
- "name": "Doubao-pro-32k",
- "maxContext": 32000,
- "maxResponse": 4000,
- "quoteMaxToken": 32000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "Doubao-pro-128k",
- "name": "Doubao-pro-128k",
- "maxContext": 128000,
- "maxResponse": 4000,
- "quoteMaxToken": 120000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "Doubao-vision-pro-32k",
- "name": "Doubao-vision-pro-32k",
- "maxContext": 32000,
- "maxResponse": 4000,
- "quoteMaxToken": 32000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "Doubao-embedding-large",
- "name": "Doubao-embedding-large",
- "defaultToken": 512,
- "maxToken": 4096,
- "type": "embedding",
- "normalization": true
- },
- {
- "model": "Doubao-embedding",
- "name": "Doubao-embedding",
- "defaultToken": 512,
- "maxToken": 4096,
- "type": "embedding",
- "normalization": true
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/Ernie.json b/packages/service/core/ai/config/provider/Ernie.json
deleted file mode 100644
index 8af2c0d53..000000000
--- a/packages/service/core/ai/config/provider/Ernie.json
+++ /dev/null
@@ -1,87 +0,0 @@
-{
- "provider": "Ernie",
- "list": [
- {
- "model": "ERNIE-4.0-8K",
- "name": "ERNIE-4.0-8K",
- "maxContext": 8000,
- "maxResponse": 2048,
- "quoteMaxToken": 5000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "ERNIE-4.0-Turbo-8K",
- "name": "ERNIE-4.0-Turbo-8K",
- "maxContext": 8000,
- "maxResponse": 2048,
- "quoteMaxToken": 5000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "ERNIE-Lite-8K",
- "name": "ERNIE-lite-8k",
- "maxContext": 8000,
- "maxResponse": 2048,
- "quoteMaxToken": 6000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "ERNIE-Speed-128K",
- "name": "ERNIE-Speed-128K",
- "maxContext": 128000,
- "maxResponse": 4096,
- "quoteMaxToken": 120000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "Embedding-V1",
- "name": "Embedding-V1",
- "defaultToken": 512,
- "maxToken": 1000,
- "type": "embedding"
- },
- {
- "model": "tao-8k",
- "name": "tao-8k",
- "defaultToken": 512,
- "maxToken": 8000,
- "type": "embedding"
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/FishAudio.json b/packages/service/core/ai/config/provider/FishAudio.json
deleted file mode 100644
index 083d565d5..000000000
--- a/packages/service/core/ai/config/provider/FishAudio.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "provider": "FishAudio",
- "list": []
-}
\ No newline at end of file
diff --git a/packages/service/core/ai/config/provider/Gemini.json b/packages/service/core/ai/config/provider/Gemini.json
deleted file mode 100644
index 6ab859908..000000000
--- a/packages/service/core/ai/config/provider/Gemini.json
+++ /dev/null
@@ -1,214 +0,0 @@
-{
- "provider": "Gemini",
- "list": [
- {
- "model": "gemini-2.5-pro",
- "name": "gemini-2.5-pro",
- "maxContext": 1000000,
- "maxResponse": 63000,
- "quoteMaxToken": 1000000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": true,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "gemini-2.5-flash",
- "name": "gemini-2.5-flash",
- "maxContext": 1000000,
- "maxResponse": 63000,
- "quoteMaxToken": 1000000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": true,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "gemini-2.5-pro-exp-03-25",
- "name": "gemini-2.5-pro-exp-03-25",
- "maxContext": 1000000,
- "maxResponse": 63000,
- "quoteMaxToken": 1000000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "gemini-2.5-flash-preview-04-17",
- "name": "gemini-2.5-flash-preview-04-17",
- "maxContext": 1000000,
- "maxResponse": 8000,
- "quoteMaxToken": 60000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "gemini-2.0-flash",
- "name": "gemini-2.0-flash",
- "maxContext": 1000000,
- "maxResponse": 8000,
- "quoteMaxToken": 60000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "gemini-2.0-pro-exp",
- "name": "gemini-2.0-pro-exp",
- "maxContext": 2000000,
- "maxResponse": 8000,
- "quoteMaxToken": 100000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "gemini-1.5-flash",
- "name": "gemini-1.5-flash",
- "maxContext": 1000000,
- "maxResponse": 8000,
- "quoteMaxToken": 60000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "gemini-1.5-pro",
- "name": "gemini-1.5-pro",
- "maxContext": 2000000,
- "maxResponse": 8000,
- "quoteMaxToken": 60000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "gemini-2.0-flash-exp",
- "name": "gemini-2.0-flash-exp",
- "maxContext": 1000000,
- "maxResponse": 8000,
- "quoteMaxToken": 60000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "gemini-2.0-flash-thinking-exp-1219",
- "name": "gemini-2.0-flash-thinking-exp-1219",
- "maxContext": 1000000,
- "maxResponse": 8000,
- "quoteMaxToken": 60000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "gemini-2.0-flash-thinking-exp-01-21",
- "name": "gemini-2.0-flash-thinking-exp-01-21",
- "maxContext": 1000000,
- "maxResponse": 8000,
- "quoteMaxToken": 60000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "gemini-exp-1206",
- "name": "gemini-exp-1206",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 120000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "text-embedding-004",
- "name": "text-embedding-004",
- "defaultToken": 512,
- "maxToken": 2000,
- "type": "embedding"
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/Grok.json b/packages/service/core/ai/config/provider/Grok.json
deleted file mode 100644
index 40a979d7e..000000000
--- a/packages/service/core/ai/config/provider/Grok.json
+++ /dev/null
@@ -1,105 +0,0 @@
-{
- "provider": "Grok",
- "list": [
- {
- "model": "grok-4",
- "name": "grok-4",
- "maxContext": 256000,
- "maxResponse": 8000,
- "quoteMaxToken": 128000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": true,
- "toolChoice": true,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "grok-4-0709",
- "name": "grok-4-0709",
- "maxContext": 256000,
- "maxResponse": 8000,
- "quoteMaxToken": 128000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": true,
- "toolChoice": true,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "grok-3-mini",
- "name": "grok-3-mini",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 128000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "grok-3-mini-fast",
- "name": "grok-3-mini-fast",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 128000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "grok-3",
- "name": "grok-3",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 128000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "grok-3-fast",
- "name": "grok-3-fast",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 128000,
- "maxTemperature": 1,
- "showTopP": true,
- "showStopSign": true,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/Groq.json b/packages/service/core/ai/config/provider/Groq.json
deleted file mode 100644
index 0206bb0c4..000000000
--- a/packages/service/core/ai/config/provider/Groq.json
+++ /dev/null
@@ -1,37 +0,0 @@
-{
- "provider": "Groq",
- "list": [
- {
- "model": "llama-3.1-8b-instant",
- "name": "Groq-llama-3.1-8b-instant",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 60000,
- "maxTemperature": 1.2,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "llama-3.3-70b-versatile",
- "name": "Groq-llama-3.3-70b-versatile",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 60000,
- "maxTemperature": 1.2,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/Hunyuan.json b/packages/service/core/ai/config/provider/Hunyuan.json
deleted file mode 100644
index 2cfe1d305..000000000
--- a/packages/service/core/ai/config/provider/Hunyuan.json
+++ /dev/null
@@ -1,131 +0,0 @@
-{
- "provider": "Hunyuan",
- "list": [
- {
- "model": "hunyuan-large",
- "name": "hunyuan-large",
- "maxContext": 28000,
- "maxResponse": 4000,
- "quoteMaxToken": 20000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "hunyuan-lite",
- "name": "hunyuan-lite",
- "maxContext": 250000,
- "maxResponse": 6000,
- "quoteMaxToken": 100000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "hunyuan-pro",
- "name": "hunyuan-pro",
- "maxContext": 28000,
- "maxResponse": 4000,
- "quoteMaxToken": 28000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "hunyuan-standard",
- "name": "hunyuan-standard",
- "maxContext": 32000,
- "maxResponse": 2000,
- "quoteMaxToken": 20000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "hunyuan-turbo-vision",
- "name": "hunyuan-turbo-vision",
- "maxContext": 6000,
- "maxResponse": 2000,
- "quoteMaxToken": 6000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "hunyuan-turbo",
- "name": "hunyuan-turbo",
- "maxContext": 28000,
- "maxResponse": 4000,
- "quoteMaxToken": 20000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "hunyuan-vision",
- "name": "hunyuan-vision",
- "maxContext": 6000,
- "maxResponse": 2000,
- "quoteMaxToken": 4000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "hunyuan-embedding",
- "name": "hunyuan-embedding",
- "defaultToken": 512,
- "maxToken": 1024,
- "type": "embedding"
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/Intern.json b/packages/service/core/ai/config/provider/Intern.json
deleted file mode 100644
index 05426ad20..000000000
--- a/packages/service/core/ai/config/provider/Intern.json
+++ /dev/null
@@ -1,39 +0,0 @@
-{
- "provider": "Intern",
- "list": [
- {
- "model": "internlm2-pro-chat",
- "name": "internlm2-pro-chat",
- "maxContext": 32000,
- "maxResponse": 8000,
- "quoteMaxToken": 32000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "internlm3-8b-instruct",
- "name": "internlm3-8b-instruct",
- "maxContext": 32000,
- "maxResponse": 8000,
- "quoteMaxToken": 32000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/Meta.json b/packages/service/core/ai/config/provider/Meta.json
deleted file mode 100644
index a99db0bc8..000000000
--- a/packages/service/core/ai/config/provider/Meta.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "provider": "Meta",
- "list": []
-}
\ No newline at end of file
diff --git a/packages/service/core/ai/config/provider/MiniMax.json b/packages/service/core/ai/config/provider/MiniMax.json
deleted file mode 100644
index acefb86a2..000000000
--- a/packages/service/core/ai/config/provider/MiniMax.json
+++ /dev/null
@@ -1,230 +0,0 @@
-{
- "provider": "MiniMax",
- "list": [
- {
- "model": "MiniMax-Text-01",
- "name": "MiniMax-Text-01",
- "maxContext": 1000000,
- "maxResponse": 1000000,
- "quoteMaxToken": 100000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "abab6.5s-chat",
- "name": "MiniMax-abab6.5s",
- "maxContext": 245000,
- "maxResponse": 10000,
- "quoteMaxToken": 240000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "speech-01-turbo",
- "name": "speech-01-turbo",
- "voices": [
- {
- "label": "male-qn-qingse",
- "value": "male-qn-qingse"
- },
- {
- "label": "male-qn-jingying",
- "value": "male-qn-jingying"
- },
- {
- "label": "male-qn-badao",
- "value": "male-qn-badao"
- },
- {
- "label": "male-qn-daxuesheng",
- "value": "male-qn-daxuesheng"
- },
- {
- "label": "female-shaonv",
- "value": "female-shaonv"
- },
- {
- "label": "female-yujie",
- "value": "female-yujie"
- },
- {
- "label": "female-chengshu",
- "value": "female-chengshu"
- },
- {
- "label": "female-tianmei",
- "value": "female-tianmei"
- },
- {
- "label": "presenter_male",
- "value": "presenter_male"
- },
- {
- "label": "presenter_female",
- "value": "presenter_female"
- },
- {
- "label": "audiobook_male_1",
- "value": "audiobook_male_1"
- },
- {
- "label": "audiobook_male_2",
- "value": "audiobook_male_2"
- },
- {
- "label": "audiobook_female_1",
- "value": "audiobook_female_1"
- },
- {
- "label": "audiobook_female_2",
- "value": "audiobook_female_2"
- },
- {
- "label": "male-qn-qingse-jingpin",
- "value": "male-qn-qingse-jingpin"
- },
- {
- "label": "male-qn-jingying-jingpin",
- "value": "male-qn-jingying-jingpin"
- },
- {
- "label": "male-qn-badao-jingpin",
- "value": "male-qn-badao-jingpin"
- },
- {
- "label": "male-qn-daxuesheng-jingpin",
- "value": "male-qn-daxuesheng-jingpin"
- },
- {
- "label": "female-shaonv-jingpin",
- "value": "female-shaonv-jingpin"
- },
- {
- "label": "female-yujie-jingpin",
- "value": "female-yujie-jingpin"
- },
- {
- "label": "female-chengshu-jingpin",
- "value": "female-chengshu-jingpin"
- },
- {
- "label": "female-tianmei-jingpin",
- "value": "female-tianmei-jingpin"
- },
- {
- "label": "clever_boy",
- "value": "clever_boy"
- },
- {
- "label": "cute_boy",
- "value": "cute_boy"
- },
- {
- "label": "lovely_girl",
- "value": "lovely_girl"
- },
- {
- "label": "cartoon_pig",
- "value": "cartoon_pig"
- },
- {
- "label": "bingjiao_didi",
- "value": "bingjiao_didi"
- },
- {
- "label": "junlang_nanyou",
- "value": "junlang_nanyou"
- },
- {
- "label": "chunzhen_xuedi",
- "value": "chunzhen_xuedi"
- },
- {
- "label": "lengdan_xiongzhang",
- "value": "lengdan_xiongzhang"
- },
- {
- "label": "badao_shaoye",
- "value": "badao_shaoye"
- },
- {
- "label": "tianxin_xiaoling",
- "value": "tianxin_xiaoling"
- },
- {
- "label": "qiaopi_mengmei",
- "value": "qiaopi_mengmei"
- },
- {
- "label": "wumei_yujie",
- "value": "wumei_yujie"
- },
- {
- "label": "diadia_xuemei",
- "value": "diadia_xuemei"
- },
- {
- "label": "danya_xuejie",
- "value": "danya_xuejie"
- },
- {
- "label": "Santa_Claus",
- "value": "Santa_Claus"
- },
- {
- "label": "Grinch",
- "value": "Grinch"
- },
- {
- "label": "Rudolph",
- "value": "Rudolph"
- },
- {
- "label": "Arnold",
- "value": "Arnold"
- },
- {
- "label": "Charming_Santa",
- "value": "Charming_Santa"
- },
- {
- "label": "Charming_Lady",
- "value": "Charming_Lady"
- },
- {
- "label": "Sweet_Girl",
- "value": "Sweet_Girl"
- },
- {
- "label": "Cute_Elf",
- "value": "Cute_Elf"
- },
- {
- "label": "Attractive_Girl",
- "value": "Attractive_Girl"
- },
- {
- "label": "Serene_Woman",
- "value": "Serene_Woman"
- }
- ],
- "type": "tts"
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/MistralAI.json b/packages/service/core/ai/config/provider/MistralAI.json
deleted file mode 100644
index ebf0085d2..000000000
--- a/packages/service/core/ai/config/provider/MistralAI.json
+++ /dev/null
@@ -1,73 +0,0 @@
-{
- "provider": "MistralAI",
- "list": [
- {
- "model": "ministral-3b-latest",
- "name": "Ministral-3b-latest",
- "maxContext": 130000,
- "maxResponse": 8000,
- "quoteMaxToken": 60000,
- "maxTemperature": 1.2,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "ministral-8b-latest",
- "name": "Ministral-8b-latest",
- "maxContext": 130000,
- "maxResponse": 8000,
- "quoteMaxToken": 60000,
- "maxTemperature": 1.2,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "mistral-large-latest",
- "name": "Mistral-large-latest",
- "maxContext": 130000,
- "maxResponse": 8000,
- "quoteMaxToken": 60000,
- "maxTemperature": 1.2,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "mistral-small-latest",
- "name": "Mistral-small-latest",
- "maxContext": 32000,
- "maxResponse": 4000,
- "quoteMaxToken": 32000,
- "maxTemperature": 1.2,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/Moka.json b/packages/service/core/ai/config/provider/Moka.json
deleted file mode 100644
index 90b68c9ff..000000000
--- a/packages/service/core/ai/config/provider/Moka.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "provider": "Moka",
- "list": []
-}
\ No newline at end of file
diff --git a/packages/service/core/ai/config/provider/Moonshot.json b/packages/service/core/ai/config/provider/Moonshot.json
deleted file mode 100644
index 2fdf74939..000000000
--- a/packages/service/core/ai/config/provider/Moonshot.json
+++ /dev/null
@@ -1,181 +0,0 @@
-{
- "provider": "Moonshot",
- "list": [
- {
- "model": "kimi-k2-0711-preview",
- "name": "kimi-k2-0711-preview",
- "maxContext": 128000,
- "maxResponse": 32000,
- "quoteMaxToken": 128000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "kimi-latest-8k",
- "name": "kimi-latest-8k",
- "maxContext": 8000,
- "maxResponse": 4000,
- "quoteMaxToken": 6000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "kimi-latest-32k",
- "name": "kimi-latest-32k",
- "maxContext": 32000,
- "maxResponse": 16000,
- "quoteMaxToken": 32000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "kimi-latest-128k",
- "name": "kimi-latest-128k",
- "maxContext": 128000,
- "maxResponse": 32000,
- "quoteMaxToken": 128000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "moonshot-v1-8k",
- "name": "moonshot-v1-8k",
- "maxContext": 8000,
- "maxResponse": 4000,
- "quoteMaxToken": 6000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "moonshot-v1-32k",
- "name": "moonshot-v1-32k",
- "maxContext": 32000,
- "maxResponse": 4000,
- "quoteMaxToken": 32000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "moonshot-v1-128k",
- "name": "moonshot-v1-128k",
- "maxContext": 128000,
- "maxResponse": 4000,
- "quoteMaxToken": 60000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "moonshot-v1-8k-vision-preview",
- "name": "moonshot-v1-8k-vision-preview",
- "maxContext": 8000,
- "maxResponse": 4000,
- "quoteMaxToken": 6000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "moonshot-v1-32k-vision-preview",
- "name": "moonshot-v1-32k-vision-preview",
- "maxContext": 32000,
- "maxResponse": 4000,
- "quoteMaxToken": 32000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "moonshot-v1-128k-vision-preview",
- "name": "moonshot-v1-128k-vision-preview",
- "maxContext": 128000,
- "maxResponse": 4000,
- "quoteMaxToken": 60000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/Ollama.json b/packages/service/core/ai/config/provider/Ollama.json
deleted file mode 100644
index 6343aa950..000000000
--- a/packages/service/core/ai/config/provider/Ollama.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "provider": "Ollama",
- "list": []
-}
\ No newline at end of file
diff --git a/packages/service/core/ai/config/provider/OpenAI.json b/packages/service/core/ai/config/provider/OpenAI.json
deleted file mode 100644
index 27c2ac3fd..000000000
--- a/packages/service/core/ai/config/provider/OpenAI.json
+++ /dev/null
@@ -1,301 +0,0 @@
-{
- "provider": "OpenAI",
- "list": [
- {
- "model": "gpt-4.1",
- "name": "gpt-4.1",
- "maxContext": 1000000,
- "maxResponse": 32000,
- "quoteMaxToken": 1000000,
- "maxTemperature": 1.2,
- "showTopP": true,
- "responseFormatList": ["text", "json_object", "json_schema"],
- "showStopSign": true,
- "vision": true,
- "toolChoice": true,
- "functionCall": true,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "gpt-4.1-mini",
- "name": "gpt-4.1-mini",
- "maxContext": 1000000,
- "maxResponse": 32000,
- "quoteMaxToken": 1000000,
- "maxTemperature": 1.2,
- "showTopP": true,
- "responseFormatList": ["text", "json_object", "json_schema"],
- "showStopSign": true,
- "vision": true,
- "toolChoice": true,
- "functionCall": true,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "gpt-4.1-nano",
- "name": "gpt-4.1-nano",
- "maxContext": 1000000,
- "maxResponse": 32000,
- "quoteMaxToken": 1000000,
- "maxTemperature": 1.2,
- "showTopP": true,
- "responseFormatList": ["text", "json_object", "json_schema"],
- "showStopSign": true,
- "vision": true,
- "toolChoice": true,
- "functionCall": true,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "gpt-4o-mini",
- "name": "GPT-4o-mini",
- "maxContext": 128000,
- "maxResponse": 16000,
- "quoteMaxToken": 60000,
- "maxTemperature": 1.2,
- "showTopP": true,
- "responseFormatList": ["text", "json_object", "json_schema"],
- "showStopSign": true,
- "vision": true,
- "toolChoice": true,
- "functionCall": true,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "gpt-4o",
- "name": "GPT-4o",
- "maxContext": 128000,
- "maxResponse": 4000,
- "quoteMaxToken": 60000,
- "maxTemperature": 1.2,
- "showTopP": true,
- "responseFormatList": ["text", "json_object", "json_schema"],
- "showStopSign": true,
- "vision": true,
- "toolChoice": true,
- "functionCall": true,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm"
- },
- {
- "model": "o4-mini",
- "name": "o4-mini",
- "maxContext": 200000,
- "maxResponse": 100000,
- "quoteMaxToken": 120000,
- "maxTemperature": null,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {
- "max_tokens": "max_completion_tokens"
- },
- "type": "llm",
- "showTopP": true,
- "showStopSign": false
- },
- {
- "model": "o3",
- "name": "o3",
- "maxContext": 200000,
- "maxResponse": 100000,
- "quoteMaxToken": 120000,
- "maxTemperature": null,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {
- "max_tokens": "max_completion_tokens"
- },
- "type": "llm",
- "showTopP": true,
- "showStopSign": false
- },
- {
- "model": "o3-mini",
- "name": "o3-mini",
- "maxContext": 200000,
- "maxResponse": 100000,
- "quoteMaxToken": 120000,
- "maxTemperature": null,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {
- "max_tokens": "max_completion_tokens"
- },
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "o1",
- "name": "o1",
- "maxContext": 195000,
- "maxResponse": 8000,
- "quoteMaxToken": 120000,
- "maxTemperature": null,
- "vision": true,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {
- "max_tokens": "max_completion_tokens"
- },
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "o1-mini",
- "name": "o1-mini",
- "maxContext": 128000,
- "maxResponse": 4000,
- "quoteMaxToken": 120000,
- "maxTemperature": null,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {
- "max_tokens": "max_completion_tokens"
- },
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "o1-preview",
- "name": "o1-preview",
- "maxContext": 128000,
- "maxResponse": 4000,
- "quoteMaxToken": 120000,
- "maxTemperature": null,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {
- "stream": false
- },
- "fieldMap": {
- "max_tokens": "max_completion_tokens"
- },
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "gpt-3.5-turbo",
- "name": "gpt-3.5-turbo",
- "maxContext": 16000,
- "maxResponse": 4000,
- "quoteMaxToken": 13000,
- "maxTemperature": 1.2,
- "showTopP": true,
- "showStopSign": true,
- "vision": false,
- "toolChoice": true,
- "functionCall": true,
- "defaultSystemChatPrompt": "",
- "type": "llm"
- },
- {
- "model": "gpt-4-turbo",
- "name": "gpt-4-turbo",
- "maxContext": 128000,
- "maxResponse": 4000,
- "quoteMaxToken": 60000,
- "maxTemperature": 1.2,
- "showTopP": true,
- "showStopSign": true,
- "vision": true,
- "toolChoice": true,
- "functionCall": true,
- "defaultSystemChatPrompt": "",
- "type": "llm"
- },
- {
- "model": "text-embedding-3-large",
- "name": "text-embedding-3-large",
- "defaultToken": 512,
- "maxToken": 8000,
- "defaultConfig": {
- "dimensions": 1024
- },
- "type": "embedding"
- },
- {
- "model": "text-embedding-3-small",
- "name": "text-embedding-3-small",
- "defaultToken": 512,
- "maxToken": 8000,
- "type": "embedding"
- },
- {
- "model": "text-embedding-ada-002",
- "name": "text-embedding-ada-002",
- "defaultToken": 512,
- "maxToken": 8000,
- "type": "embedding"
- },
- {
- "model": "tts-1",
- "name": "TTS1",
- "voices": [
- {
- "label": "Alloy",
- "value": "alloy"
- },
- {
- "label": "Echo",
- "value": "echo"
- },
- {
- "label": "Fable",
- "value": "fable"
- },
- {
- "label": "Onyx",
- "value": "onyx"
- },
- {
- "label": "Nova",
- "value": "nova"
- },
- {
- "label": "Shimmer",
- "value": "shimmer"
- }
- ],
- "type": "tts"
- },
- {
- "model": "whisper-1",
- "name": "whisper-1",
- "type": "stt"
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/Other.json b/packages/service/core/ai/config/provider/Other.json
deleted file mode 100644
index 4405e6086..000000000
--- a/packages/service/core/ai/config/provider/Other.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "provider": "Other",
- "list": []
-}
\ No newline at end of file
diff --git a/packages/service/core/ai/config/provider/PPIO.json b/packages/service/core/ai/config/provider/PPIO.json
deleted file mode 100644
index a59ca6f06..000000000
--- a/packages/service/core/ai/config/provider/PPIO.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "provider": "PPIO",
- "list": []
-}
diff --git a/packages/service/core/ai/config/provider/Qwen.json b/packages/service/core/ai/config/provider/Qwen.json
deleted file mode 100644
index 2a44fc067..000000000
--- a/packages/service/core/ai/config/provider/Qwen.json
+++ /dev/null
@@ -1,440 +0,0 @@
-{
- "provider": "Qwen",
- "list": [
- {
- "model": "qwen-max",
- "name": "Qwen-max",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 120000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "qwen-vl-max",
- "name": "qwen-vl-max",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 120000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "qwen-plus",
- "name": "Qwen-plus",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 120000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "qwen-vl-plus",
- "name": "qwen-vl-plus",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 120000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "qwen-turbo",
- "name": "Qwen-turbo",
- "maxContext": 1000000,
- "maxResponse": 8000,
- "quoteMaxToken": 1000000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "qwen3-235b-a22b",
- "name": "qwen3-235b-a22b",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 100000,
- "maxTemperature": 1,
- "vision": false,
- "reasoning": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {
- "stream": true
- },
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "qwen3-32b",
- "name": "qwen3-32b",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 100000,
- "maxTemperature": 1,
- "vision": false,
- "reasoning": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {
- "stream": true
- },
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "qwen3-30b-a3b",
- "name": "qwen3-30b-a3b",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 100000,
- "maxTemperature": 1,
- "vision": false,
- "reasoning": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {
- "stream": true
- },
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "qwen3-14b",
- "name": "qwen3-14b",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 100000,
- "maxTemperature": 1,
- "vision": false,
- "reasoning": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {
- "stream": true
- },
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "qwen3-8b",
- "name": "qwen3-8b",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 100000,
- "maxTemperature": 1,
- "vision": false,
- "reasoning": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {
- "stream": true
- },
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "qwen3-4b",
- "name": "qwen3-4b",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 100000,
- "maxTemperature": 1,
- "vision": false,
- "reasoning": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {
- "stream": true
- },
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "qwen3-1.7b",
- "name": "qwen3-1.7b",
- "maxContext": 32000,
- "maxResponse": 8000,
- "quoteMaxToken": 30000,
- "maxTemperature": 1,
- "vision": false,
- "reasoning": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {
- "stream": true
- },
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "qwen3-0.6b",
- "name": "qwen3-0.6b",
- "maxContext": 32000,
- "maxResponse": 8000,
- "quoteMaxToken": 30000,
- "maxTemperature": 1,
- "vision": false,
- "reasoning": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {
- "stream": true
- },
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "qwq-plus",
- "name": "qwq-plus",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 100000,
- "maxTemperature": null,
- "vision": false,
- "reasoning": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "datasetProcess": false,
- "usedInClassify": false,
- "usedInExtractFields": false,
- "usedInQueryExtension": false,
- "defaultConfig": {
- "stream": true
- },
- "fieldMap": {},
- "type": "llm",
- "showTopP": false,
- "showStopSign": false
- },
- {
- "model": "qwq-32b",
- "name": "qwq-32b",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 100000,
- "maxTemperature": null,
- "vision": false,
- "reasoning": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "datasetProcess": false,
- "usedInClassify": false,
- "usedInExtractFields": false,
- "usedInQueryExtension": false,
- "defaultConfig": {
- "stream": true
- },
- "fieldMap": {},
- "type": "llm",
- "showTopP": false,
- "showStopSign": false
- },
- {
- "model": "qwen-coder-turbo",
- "name": "qwen-coder-turbo",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 50000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "qwen2.5-7b-instruct",
- "name": "qwen2.5-7b-instruct",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 50000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "qwen2.5-14b-instruct",
- "name": "qwen2.5-14b-instruct",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 50000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "qwen2.5-32b-instruct",
- "name": "qwen2.5-32b-instruct",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 50000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "qwen2.5-72b-instruct",
- "name": "Qwen2.5-72B-instruct",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 50000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true,
- "responseFormatList": ["text", "json_object"]
- },
- {
- "model": "qwen-long",
- "name": "qwen-long",
- "maxContext": 10000000,
- "maxResponse": 6000,
- "quoteMaxToken": 10000000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "datasetProcess": false,
- "usedInClassify": false,
- "usedInExtractFields": false,
- "usedInQueryExtension": false,
- "usedInToolCall": false,
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": false,
- "showStopSign": false
- },
- {
- "model": "text-embedding-v4",
- "name": "text-embedding-v4",
- "defaultToken": 512,
- "maxToken": 8000,
- "type": "embedding",
- "defaultConfig": {
- "dimensions": 1536
- }
- },
- {
- "model": "text-embedding-v3",
- "name": "text-embedding-v3",
- "defaultToken": 512,
- "maxToken": 8000,
- "type": "embedding"
- },
- {
- "model": "gte-rerank-v2",
- "name": "gte-rerank-v2",
- "type": "rerank"
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/Siliconflow.json b/packages/service/core/ai/config/provider/Siliconflow.json
deleted file mode 100644
index a0b807682..000000000
--- a/packages/service/core/ai/config/provider/Siliconflow.json
+++ /dev/null
@@ -1,194 +0,0 @@
-{
- "provider": "Siliconflow",
- "list": [
- {
- "model": "Qwen/Qwen2.5-72B-Instruct",
- "name": "Qwen/Qwen2.5-72B-Instruct",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 50000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "Qwen/Qwen2-VL-72B-Instruct",
- "name": "Qwen/Qwen2-VL-72B-Instruct",
- "maxContext": 32000,
- "maxResponse": 4000,
- "quoteMaxToken": 32000,
- "maxTemperature": 1,
- "censor": false,
- "vision": true,
- "datasetProcess": false,
- "usedInClassify": false,
- "usedInExtractFields": false,
- "usedInToolCall": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "deepseek-ai/DeepSeek-V2.5",
- "name": "deepseek-ai/DeepSeek-V2.5",
- "maxContext": 32000,
- "maxResponse": 4000,
- "quoteMaxToken": 32000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": true,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "BAAI/bge-m3",
- "name": "BAAI/bge-m3",
- "defaultToken": 512,
- "maxToken": 8000,
- "type": "embedding"
- },
- {
- "model": "FunAudioLLM/CosyVoice2-0.5B",
- "name": "FunAudioLLM/CosyVoice2-0.5B",
- "voices": [
- {
- "label": "alex",
- "value": "FunAudioLLM/CosyVoice2-0.5B:alex"
- },
- {
- "label": "anna",
- "value": "FunAudioLLM/CosyVoice2-0.5B:anna"
- },
- {
- "label": "bella",
- "value": "FunAudioLLM/CosyVoice2-0.5B:bella"
- },
- {
- "label": "benjamin",
- "value": "FunAudioLLM/CosyVoice2-0.5B:benjamin"
- },
- {
- "label": "charles",
- "value": "FunAudioLLM/CosyVoice2-0.5B:charles"
- },
- {
- "label": "claire",
- "value": "FunAudioLLM/CosyVoice2-0.5B:claire"
- },
- {
- "label": "david",
- "value": "FunAudioLLM/CosyVoice2-0.5B:david"
- },
- {
- "label": "diana",
- "value": "FunAudioLLM/CosyVoice2-0.5B:diana"
- }
- ],
- "type": "tts"
- },
- {
- "model": "RVC-Boss/GPT-SoVITS",
- "name": "RVC-Boss/GPT-SoVITS",
- "voices": [
- {
- "label": "alex",
- "value": "RVC-Boss/GPT-SoVITS:alex"
- },
- {
- "label": "anna",
- "value": "RVC-Boss/GPT-SoVITS:anna"
- },
- {
- "label": "bella",
- "value": "RVC-Boss/GPT-SoVITS:bella"
- },
- {
- "label": "benjamin",
- "value": "RVC-Boss/GPT-SoVITS:benjamin"
- },
- {
- "label": "charles",
- "value": "RVC-Boss/GPT-SoVITS:charles"
- },
- {
- "label": "claire",
- "value": "RVC-Boss/GPT-SoVITS:claire"
- },
- {
- "label": "david",
- "value": "RVC-Boss/GPT-SoVITS:david"
- },
- {
- "label": "diana",
- "value": "RVC-Boss/GPT-SoVITS:diana"
- }
- ],
- "type": "tts"
- },
- {
- "model": "fishaudio/fish-speech-1.5",
- "name": "fish-speech-1.5",
- "voices": [
- {
- "label": "alex",
- "value": "fishaudio/fish-speech-1.5:alex"
- },
- {
- "label": "anna",
- "value": "fishaudio/fish-speech-1.5:anna"
- },
- {
- "label": "bella",
- "value": "fishaudio/fish-speech-1.5:bella"
- },
- {
- "label": "benjamin",
- "value": "fishaudio/fish-speech-1.5:benjamin"
- },
- {
- "label": "charles",
- "value": "fishaudio/fish-speech-1.5:charles"
- },
- {
- "label": "claire",
- "value": "fishaudio/fish-speech-1.5:claire"
- },
- {
- "label": "david",
- "value": "fishaudio/fish-speech-1.5:david"
- },
- {
- "label": "diana",
- "value": "fishaudio/fish-speech-1.5:diana"
- }
- ],
- "type": "tts"
- },
- {
- "model": "FunAudioLLM/SenseVoiceSmall",
- "name": "FunAudioLLM/SenseVoiceSmall",
- "type": "stt"
- },
- {
- "model": "BAAI/bge-reranker-v2-m3",
- "name": "BAAI/bge-reranker-v2-m3",
- "type": "rerank"
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/SparkDesk.json b/packages/service/core/ai/config/provider/SparkDesk.json
deleted file mode 100644
index 766e18a8a..000000000
--- a/packages/service/core/ai/config/provider/SparkDesk.json
+++ /dev/null
@@ -1,99 +0,0 @@
-{
- "provider": "SparkDesk",
- "list": [
- {
- "model": "lite",
- "name": "SparkDesk-lite",
- "maxContext": 32000,
- "maxResponse": 4000,
- "quoteMaxToken": 32000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "generalv3",
- "name": "SparkDesk-Pro",
- "maxContext": 8000,
- "maxResponse": 8000,
- "quoteMaxToken": 8000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "pro-128k",
- "name": "SparkDesk-Pro-128k",
- "maxContext": 128000,
- "maxResponse": 4000,
- "quoteMaxToken": 128000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "generalv3.5",
- "name": "SparkDesk-max",
- "maxContext": 8000,
- "maxResponse": 8000,
- "quoteMaxToken": 8000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "max-32k",
- "name": "SparkDesk-max-32k",
- "maxContext": 32000,
- "maxResponse": 8000,
- "quoteMaxToken": 32000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "4.0Ultra",
- "name": "SparkDesk-v4.0 Ultra",
- "maxContext": 8000,
- "maxResponse": 8000,
- "quoteMaxToken": 8000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/StepFun.json b/packages/service/core/ai/config/provider/StepFun.json
deleted file mode 100644
index 3e9bddb90..000000000
--- a/packages/service/core/ai/config/provider/StepFun.json
+++ /dev/null
@@ -1,253 +0,0 @@
-{
- "provider": "StepFun",
- "list": [
- {
- "model": "step-1-flash",
- "name": "step-1-flash",
- "maxContext": 8000,
- "maxResponse": 4000,
- "quoteMaxToken": 6000,
- "maxTemperature": 2,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "step-1-8k",
- "name": "step-1-8k",
- "maxContext": 8000,
- "maxResponse": 8000,
- "quoteMaxToken": 8000,
- "maxTemperature": 2,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "step-1-32k",
- "name": "step-1-32k",
- "maxContext": 32000,
- "maxResponse": 8000,
- "quoteMaxToken": 32000,
- "maxTemperature": 2,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "step-1-128k",
- "name": "step-1-128k",
- "maxContext": 128000,
- "maxResponse": 8000,
- "quoteMaxToken": 128000,
- "maxTemperature": 2,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "step-1-256k",
- "name": "step-1-256k",
- "maxContext": 256000,
- "maxResponse": 8000,
- "quoteMaxToken": 256000,
- "maxTemperature": 2,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "step-1o-vision-32k",
- "name": "step-1o-vision-32k",
- "maxContext": 32000,
- "quoteMaxToken": 32000,
- "maxResponse": 8000,
- "maxTemperature": 2,
- "vision": true,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "step-1v-8k",
- "name": "step-1v-8k",
- "maxContext": 8000,
- "maxResponse": 8000,
- "quoteMaxToken": 8000,
- "maxTemperature": 2,
- "vision": true,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "step-1v-32k",
- "name": "step-1v-32k",
- "maxContext": 32000,
- "quoteMaxToken": 32000,
- "maxResponse": 8000,
- "maxTemperature": 2,
- "vision": true,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "step-2-mini",
- "name": "step-2-mini",
- "maxContext": 8000,
- "maxResponse": 4000,
- "quoteMaxToken": 6000,
- "maxTemperature": 2,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "step-2-16k",
- "name": "step-2-16k",
- "maxContext": 16000,
- "maxResponse": 4000,
- "quoteMaxToken": 4000,
- "maxTemperature": 2,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "step-2-16k-exp",
- "name": "step-2-16k-exp",
- "maxContext": 16000,
- "maxResponse": 4000,
- "quoteMaxToken": 4000,
- "maxTemperature": 2,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "step-tts-mini",
- "name": "step-tts-mini",
- "voices": [
- {
- "label": "cixingnansheng",
- "value": "cixingnansheng"
- },
- {
- "label": "zhengpaiqingnian",
- "value": "zhengpaiqingnian"
- },
- {
- "label": "yuanqinansheng",
- "value": "yuanqinansheng"
- },
- {
- "label": "qingniandaxuesheng",
- "value": "qingniandaxuesheng"
- },
- {
- "label": "boyinnansheng",
- "value": "boyinnansheng"
- },
- {
- "label": "ruyananshi",
- "value": "ruyananshi"
- },
- {
- "label": "shenchennanyin",
- "value": "shenchennanyin"
- },
- {
- "label": "qinqienvsheng",
- "value": "qinqienvsheng"
- },
- {
- "label": "wenrounvsheng",
- "value": "wenrounvsheng"
- },
- {
- "label": "jilingshaonv",
- "value": "jilingshaonv"
- },
- {
- "label": "yuanqishaonv",
- "value": "yuanqishaonv"
- },
- {
- "label": "ruanmengnvsheng",
- "value": "ruanmengnvsheng"
- },
- {
- "label": "youyanvsheng",
- "value": "youyanvsheng"
- },
- {
- "label": "lengyanyujie",
- "value": "lengyanyujie"
- },
- {
- "label": "shuangkuaijiejie",
- "value": "shuangkuaijiejie"
- },
- {
- "label": "wenjingxuejie",
- "value": "wenjingxuejie"
- },
- {
- "label": "linjiajiejie",
- "value": "linjiajiejie"
- },
- {
- "label": "linjiameimei",
- "value": "linjiameimei"
- },
- {
- "label": "zhixingjiejie",
- "value": "zhixingjiejie"
- }
- ],
- "type": "tts"
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/Yi.json b/packages/service/core/ai/config/provider/Yi.json
deleted file mode 100644
index 5e1007a55..000000000
--- a/packages/service/core/ai/config/provider/Yi.json
+++ /dev/null
@@ -1,39 +0,0 @@
-{
- "provider": "Yi",
- "list": [
- {
- "model": "yi-lightning",
- "name": "yi-lightning",
- "maxContext": 16000,
- "maxResponse": 4000,
- "quoteMaxToken": 12000,
- "maxTemperature": 1,
- "vision": false,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- },
- {
- "model": "yi-vision-v2",
- "name": "yi-vision-v2",
- "maxContext": 16000,
- "maxResponse": 4000,
- "quoteMaxToken": 12000,
- "maxTemperature": 1,
- "vision": true,
- "toolChoice": false,
- "functionCall": false,
- "defaultSystemChatPrompt": "",
- "defaultConfig": {},
- "fieldMap": {},
- "type": "llm",
- "showTopP": true,
- "showStopSign": true
- }
- ]
-}
diff --git a/packages/service/core/ai/config/provider/jina.json b/packages/service/core/ai/config/provider/jina.json
deleted file mode 100644
index cffdf78ad..000000000
--- a/packages/service/core/ai/config/provider/jina.json
+++ /dev/null
@@ -1,22 +0,0 @@
-{
- "provider": "Jina",
- "list": [
- {
- "type": "embedding",
- "model": "jina-embeddings-v3",
- "name": "jina-embeddings-v3",
- "defaultToken": 512,
- "maxToken": 8000
- },
- {
- "model": "jina-reranker-v2-base-multilingual",
- "name": "jina-reranker-v2-base-multilingual",
- "type": "rerank"
- },
- {
- "model": "jina-reranker-m0",
- "name": "jina-reranker-m0",
- "type": "rerank"
- }
- ]
-}
diff --git a/packages/service/core/ai/config/utils.ts b/packages/service/core/ai/config/utils.ts
index d02d0a850..9aabd64cb 100644
--- a/packages/service/core/ai/config/utils.ts
+++ b/packages/service/core/ai/config/utils.ts
@@ -1,5 +1,3 @@
-import path from 'path';
-import * as fs from 'fs';
import { type SystemModelItemType } from '../type';
import { ModelTypeEnum } from '@fastgpt/global/core/ai/model';
import { MongoSystemModel } from './schema';
@@ -11,34 +9,16 @@ import {
type RerankModelItemType
} from '@fastgpt/global/core/ai/model.d';
import { debounce } from 'lodash';
-import {
- getModelProvider,
- type ModelProviderIdType,
- type ModelProviderType
-} from '@fastgpt/global/core/ai/provider';
+import { getModelProvider } from '@fastgpt/global/core/ai/provider';
import { findModelFromAlldata } from '../model';
import {
reloadFastGPTConfigBuffer,
updateFastGPTConfigBuffer
} from '../../../common/system/config/controller';
import { delay } from '@fastgpt/global/common/system/utils';
+import { pluginClient } from '../../../thirdProvider/fastgptPlugin';
+import { setCron } from '../../../common/system/cron';
-const getModelConfigBaseUrl = () => {
- const currentFileUrl = new URL(import.meta.url);
- const filePath = decodeURIComponent(
- process.platform === 'win32'
- ? currentFileUrl.pathname.substring(1) // Remove leading slash on Windows
- : currentFileUrl.pathname
- );
- const modelsPath = path.join(path.dirname(filePath), 'provider');
- return modelsPath;
-};
-
-/*
- TODO: 分优先级读取:
- 1. 有外部挂载目录,则读取外部的
- 2. 没有外部挂载目录,则读取本地的。然后试图拉取云端的进行覆盖。
-*/
export const loadSystemModels = async (init = false) => {
const pushModel = (model: SystemModelItemType) => {
global.systemModelList.push(model);
@@ -108,17 +88,19 @@ export const loadSystemModels = async (init = false) => {
global.systemDefaultModel = {};
try {
- const dbModels = await MongoSystemModel.find({}).lean();
+ // Get model from db and plugin
+ const [dbModels, systemModels] = await Promise.all([
+ MongoSystemModel.find({}).lean(),
+ pluginClient.model.list().then((res) => {
+ if (res.status === 200) return res.body;
+ console.error('Get fastGPT plugin model error');
+ return [];
+ })
+ ]);
// Load system model from local
- const modelsPath = getModelConfigBaseUrl();
- const providerList = await fs.promises.readdir(modelsPath);
await Promise.all(
- providerList.map(async (name) => {
- const fileContent = (await import(`./provider/${name}`))?.default as {
- provider: ModelProviderIdType;
- list: SystemModelItemType[];
- };
+ systemModels.map(async (model) => {
const mergeObject = (obj1: any, obj2: any) => {
if (!obj1 && !obj2) return undefined;
const formatObj1 = typeof obj1 === 'object' ? obj1 : {};
@@ -126,27 +108,24 @@ export const loadSystemModels = async (init = false) => {
return { ...formatObj1, ...formatObj2 };
};
- fileContent.list.forEach((fileModel) => {
- const dbModel = dbModels.find((item) => item.model === fileModel.model);
+ const dbModel = dbModels.find((item) => item.model === model.model);
- const modelData: any = {
- ...fileModel,
- ...dbModel?.metadata,
- // @ts-ignore
- defaultConfig: mergeObject(fileModel.defaultConfig, dbModel?.metadata?.defaultConfig),
- // @ts-ignore
- fieldMap: mergeObject(fileModel.fieldMap, dbModel?.metadata?.fieldMap),
- provider: getModelProvider(dbModel?.metadata?.provider || fileContent.provider).id,
- type: dbModel?.metadata?.type || fileModel.type,
- isCustom: false
- };
-
- pushModel(modelData);
- });
+ const modelData: any = {
+ ...model,
+ ...dbModel?.metadata,
+ // @ts-ignore
+ defaultConfig: mergeObject(model.defaultConfig, dbModel?.metadata?.defaultConfig),
+ // @ts-ignore
+ fieldMap: mergeObject(model.fieldMap, dbModel?.metadata?.fieldMap),
+ provider: getModelProvider(dbModel?.metadata?.provider || (model.provider as any)).id,
+ type: dbModel?.metadata?.type || model.type,
+ isCustom: false
+ };
+ pushModel(modelData);
})
);
- // Custom model
+ // Custom model(Not in system config)
dbModels.forEach((dbModel) => {
if (global.systemModelList.find((item) => item.model === dbModel.model)) return;
@@ -190,7 +169,18 @@ export const loadSystemModels = async (init = false) => {
return providerA.order - providerB.order;
});
- console.log('Load models success', JSON.stringify(global.systemActiveModelList, null, 2));
+ console.log(
+ `Load models success, total: ${global.systemModelList.length}, active: ${global.systemActiveModelList.length}`,
+ JSON.stringify(
+ global.systemActiveModelList.map((item) => ({
+ provider: item.provider,
+ model: item.model,
+ name: item.name
+ })),
+ null,
+ 2
+ )
+ );
} catch (error) {
console.error('Load models error', error);
// @ts-ignore
@@ -205,17 +195,16 @@ export const getSystemModelConfig = async (model: string): Promise {
+ if (res.status === 200) {
+ return res.body.find((item) => item.model === model) as SystemModelItemType;
+ }
- const config = fileContent.list.find((item) => item.model === model);
-
- if (!config) return Promise.reject('Model config is not found');
+ return Promise.reject('Can not get model config from plugin');
+ });
return {
- ...config,
+ ...modelDefaulConfig,
provider: modelData.provider,
isCustom: false
};
@@ -246,3 +235,11 @@ export const updatedReloadSystemModel = async () => {
// 3. 延迟1秒,等待其他节点刷新
await delay(1000);
};
+export const cronRefreshModels = async () => {
+ setCron('*/5 * * * *', async () => {
+ // 1. 更新模型(所有节点都会触发)
+ await loadSystemModels(true);
+ // 2. 更新缓存(仅主节点触发)
+ await updateFastGPTConfigBuffer();
+ });
+};
diff --git a/packages/service/core/app/controller.ts b/packages/service/core/app/controller.ts
index aa9ced399..55aab10f7 100644
--- a/packages/service/core/app/controller.ts
+++ b/packages/service/core/app/controller.ts
@@ -1,6 +1,7 @@
import { type AppSchema } from '@fastgpt/global/core/app/type';
import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
+import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import { MongoApp } from './schema';
import type { StoreNodeItemType } from '@fastgpt/global/core/workflow/type/node';
import { encryptSecretValue, storeSecretValue } from '../../common/secret/utils';
@@ -19,6 +20,7 @@ import { MongoResourcePermission } from '../../support/permission/schema';
import { PerResourceTypeEnum } from '@fastgpt/global/support/permission/constant';
import { removeImageByPath } from '../../common/file/image/controller';
import { mongoSessionRun } from '../../common/mongo/sessionRun';
+import { MongoAppLogKeys } from './logs/logkeysSchema';
export const beforeUpdateAppFormat = ({ nodes }: { nodes?: StoreNodeItemType[] }) => {
if (!nodes) return;
@@ -140,6 +142,10 @@ export const onDelOneApp = async ({
fields: '_id avatar'
});
+ const deletedAppIds = apps
+ .filter((app) => app.type !== AppTypeEnum.folder)
+ .map((app) => String(app._id));
+
// Remove eval job
const evalJobs = await MongoEvaluation.find(
{
@@ -191,6 +197,10 @@ export const onDelOneApp = async ({
resourceId: appId
}).session(session);
+ await MongoAppLogKeys.deleteMany({
+ appId
+ }).session(session);
+
// delete app
await MongoApp.deleteOne(
{
@@ -204,8 +214,10 @@ export const onDelOneApp = async ({
};
if (session) {
- return del(session);
+ await del(session);
+ return deletedAppIds;
}
- return mongoSessionRun(del);
+ await mongoSessionRun(del);
+ return deletedAppIds;
};
diff --git a/packages/service/core/app/logs/logkeysSchema.ts b/packages/service/core/app/logs/logkeysSchema.ts
new file mode 100644
index 000000000..40f32b94c
--- /dev/null
+++ b/packages/service/core/app/logs/logkeysSchema.ts
@@ -0,0 +1,32 @@
+import type { AppLogKeysSchemaType } from '@fastgpt/global/core/app/logs/type';
+import { connectionMongo, getMongoModel } from '../../../common/mongo';
+import { AppCollectionName } from '../schema';
+import { TeamCollectionName } from '@fastgpt/global/support/user/team/constant';
+
+const { Schema } = connectionMongo;
+
+export const AppLogKeysCollectionEnum = 'app_log_keys';
+
+const AppLogKeysSchema = new Schema({
+ teamId: {
+ type: Schema.Types.ObjectId,
+ ref: TeamCollectionName,
+ required: true
+ },
+ appId: {
+ type: Schema.Types.ObjectId,
+ ref: AppCollectionName,
+ required: true
+ },
+ logKeys: {
+ type: Array,
+ required: true
+ }
+});
+
+AppLogKeysSchema.index({ teamId: 1, appId: 1 });
+
+export const MongoAppLogKeys = getMongoModel(
+ AppLogKeysCollectionEnum,
+ AppLogKeysSchema
+);
diff --git a/packages/service/core/app/mcp.ts b/packages/service/core/app/mcp.ts
index bc8bec246..340c3146b 100644
--- a/packages/service/core/app/mcp.ts
+++ b/packages/service/core/app/mcp.ts
@@ -1,9 +1,13 @@
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
+import type { AppSchema } from '@fastgpt/global/core/app/type';
import { type McpToolConfigType } from '@fastgpt/global/core/app/type';
import { addLog } from '../../common/system/log';
import { retryFn } from '@fastgpt/global/common/system/utils';
+import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants';
+import { MongoApp } from './schema';
+import type { McpToolDataType } from '@fastgpt/global/core/app/mcpTools/type';
export class MCPClient {
private client: Client;
@@ -128,3 +132,35 @@ export class MCPClient {
}
}
}
+
+export const getMCPChildren = async (app: AppSchema) => {
+ const isNewMcp = !!app.modules[0].toolConfig?.mcpToolSet;
+ const id = String(app._id);
+
+ if (isNewMcp) {
+ return (
+ app.modules[0].toolConfig?.mcpToolSet?.toolList.map((item) => ({
+ ...item,
+ id: `${PluginSourceEnum.mcp}-${id}/${item.name}`,
+ avatar: app.avatar
+ })) ?? []
+ );
+ } else {
+ // Old mcp toolset
+ const children = await MongoApp.find({
+ teamId: app.teamId,
+ parentId: id
+ }).lean();
+
+ return children.map((item) => {
+ const node = item.modules[0];
+ const toolData: McpToolDataType = node.inputs[0].value;
+
+ return {
+ avatar: app.avatar,
+ id: `${PluginSourceEnum.mcp}-${id}/${item.name}`,
+ ...toolData
+ };
+ });
+ }
+};
diff --git a/packages/service/core/app/plugin/controller.ts b/packages/service/core/app/plugin/controller.ts
index 661f1af2a..80caf636a 100644
--- a/packages/service/core/app/plugin/controller.ts
+++ b/packages/service/core/app/plugin/controller.ts
@@ -1,6 +1,10 @@
-import { type FlowNodeTemplateType } from '@fastgpt/global/core/workflow/type/node.d';
+import type {
+ NodeToolConfigType,
+ FlowNodeTemplateType
+} from '@fastgpt/global/core/workflow/type/node.d';
import {
FlowNodeOutputTypeEnum,
+ FlowNodeInputTypeEnum,
FlowNodeTypeEnum
} from '@fastgpt/global/core/workflow/node/constant';
import {
@@ -28,7 +32,7 @@ import {
NodeInputKeyEnum
} from '@fastgpt/global/core/workflow/constants';
import { getNanoid } from '@fastgpt/global/common/string/tools';
-import { getSystemToolList } from '../tool/api';
+import { APIGetSystemToolList } from '../tool/api';
import { Types } from '../../../common/mongo';
import type { SystemPluginConfigSchemaType } from './type';
import type {
@@ -37,37 +41,11 @@ import type {
} from '@fastgpt/global/core/workflow/type/io';
import { isProduction } from '@fastgpt/global/common/system/constants';
import { Output_Template_Error_Message } from '@fastgpt/global/core/workflow/template/output';
-
-/**
- plugin id rule:
- - personal: ObjectId
- - commercial: commercial-ObjectId
- - systemtool: systemTool-id
- (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, pluginId] = id.split('-') as [PluginSourceEnum, string | undefined];
- 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}`
- };
- }
-
- return { source, pluginId: id };
-}
+import type { RuntimeNodeItemType } from '@fastgpt/global/core/workflow/runtime/type';
+import { splitCombinePluginId } from '@fastgpt/global/core/app/plugin/utils';
+import { getMCPToolRuntimeNode } from '@fastgpt/global/core/app/mcpTools/utils';
+import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
+import { getMCPChildren } from '../mcp';
type ChildAppType = SystemPluginTemplateItemType & {
teamId?: string;
@@ -81,77 +59,102 @@ export const getSystemPluginByIdAndVersionId = async (
pluginId: string,
versionId?: string
): Promise => {
- const plugin = await (async (): Promise => {
- const plugin = await getSystemPluginById(pluginId);
+ const plugin = await getSystemToolById(pluginId);
- // Admin selected system tool
- if (plugin.associatedPluginId) {
- // The verification plugin is set as a system plugin
- const systemPlugin = await MongoSystemPlugin.findOne(
- { pluginId: plugin.id, 'customConfig.associatedPluginId': plugin.associatedPluginId },
- 'associatedPluginId'
- ).lean();
- if (!systemPlugin) return Promise.reject(PluginErrEnum.unExist);
+ // Admin selected system tool
+ if (plugin.associatedPluginId) {
+ // The verification plugin is set as a system plugin
+ const systemPlugin = await MongoSystemPlugin.findOne(
+ { pluginId: plugin.id, 'customConfig.associatedPluginId': plugin.associatedPluginId },
+ 'associatedPluginId'
+ ).lean();
+ if (!systemPlugin) return Promise.reject(PluginErrEnum.unExist);
- const app = await MongoApp.findById(plugin.associatedPluginId).lean();
- if (!app) return Promise.reject(PluginErrEnum.unExist);
-
- const version = versionId
- ? await getAppVersionById({
- appId: plugin.associatedPluginId,
- versionId,
- app
- })
- : await getAppLatestVersion(plugin.associatedPluginId, app);
- if (!version.versionId) return Promise.reject('App version not found');
- const isLatest = version.versionId
- ? await checkIsLatestVersion({
- appId: plugin.associatedPluginId,
- versionId: version.versionId
- })
- : true;
-
- return {
- ...plugin,
- workflow: {
- nodes: version.nodes,
- edges: version.edges,
- chatConfig: version.chatConfig
- },
- version: versionId ? version?.versionId : '',
- versionLabel: version?.versionName,
- isLatestVersion: isLatest,
- teamId: String(app.teamId),
- tmbId: String(app.tmbId)
- };
- }
-
- // System tool
- const versionList = (plugin.versionList as SystemPluginTemplateItemType['versionList']) || [];
-
- if (versionList.length === 0) {
- return Promise.reject('Can not find plugin version list');
- }
+ const app = await MongoApp.findById(plugin.associatedPluginId).lean();
+ if (!app) return Promise.reject(PluginErrEnum.unExist);
const version = versionId
- ? versionList.find((item) => item.value === versionId) ?? versionList[0]
- : versionList[0];
- const lastVersion = versionList[0];
+ ? await getAppVersionById({
+ appId: plugin.associatedPluginId,
+ versionId,
+ app
+ })
+ : await getAppLatestVersion(plugin.associatedPluginId, app);
+ if (!version.versionId) return Promise.reject('App version not found');
+ const isLatest = version.versionId
+ ? await checkIsLatestVersion({
+ appId: plugin.associatedPluginId,
+ versionId: version.versionId
+ })
+ : true;
return {
...plugin,
- inputs: version.inputs,
- outputs: version.outputs,
- version: versionId ? version?.value : '',
- versionLabel: versionId ? version?.value : '',
- isLatestVersion: !version || !lastVersion || version.value === lastVersion?.value
+ workflow: {
+ nodes: version.nodes,
+ edges: version.edges,
+ chatConfig: version.chatConfig
+ },
+ version: versionId ? version?.versionId : '',
+ versionLabel: version?.versionName,
+ isLatestVersion: isLatest,
+ teamId: String(app.teamId),
+ tmbId: String(app.tmbId)
};
- })();
+ }
- return plugin;
+ // System toolset
+ if (plugin.isFolder) {
+ return {
+ ...plugin,
+ inputs: [],
+ outputs: [],
+ inputList: plugin.inputList,
+ version: '',
+ isLatestVersion: true
+ };
+ }
+
+ // System tool
+ const versionList = (plugin.versionList as SystemPluginTemplateItemType['versionList']) || [];
+
+ if (versionList.length === 0) {
+ return Promise.reject('Can not find plugin version list');
+ }
+
+ const version = versionId
+ ? versionList.find((item) => item.value === versionId) ?? versionList[0]
+ : versionList[0];
+ const lastVersion = versionList[0];
+
+ // concat parent (if exists) input config
+ const parent = plugin.parentId ? await getSystemToolById(plugin.parentId) : undefined;
+ if (parent && parent.inputList) {
+ plugin?.inputs?.push({
+ key: 'system_input_config',
+ label: '',
+ renderTypeList: [FlowNodeInputTypeEnum.hidden],
+ inputList: parent.inputList
+ });
+ }
+
+ return {
+ ...plugin,
+ inputs: version.inputs,
+ outputs: version.outputs,
+ version: versionId ? version?.value : '',
+ versionLabel: versionId ? version?.value : '',
+ isLatestVersion: !version || !lastVersion || version.value === lastVersion?.value
+ };
};
-/* Format plugin to workflow preview node data */
+/*
+ Format plugin to workflow preview node data
+ Persion workflow/plugin: objectId
+ Persion mcptoolset: objectId
+ Persion mcp tool: mcp-parentId/name
+ System tool/toolset: system-toolId
+*/
export async function getChildAppPreviewNode({
appId,
versionId,
@@ -164,6 +167,8 @@ export async function getChildAppPreviewNode({
const { source, pluginId } = splitCombinePluginId(appId);
const app: ChildAppType = await (async () => {
+ // 1. App
+ // 2. MCP ToolSets
if (source === PluginSourceEnum.personal) {
const item = await MongoApp.findById(pluginId).lean();
if (!item) return Promise.reject(PluginErrEnum.unExist);
@@ -178,6 +183,17 @@ export async function getChildAppPreviewNode({
})
: true;
+ if (item.type === AppTypeEnum.toolSet) {
+ const children = await getMCPChildren(item);
+ version.nodes[0].toolConfig = {
+ mcpToolSet: {
+ toolId: pluginId,
+ toolList: children,
+ url: ''
+ }
+ };
+ }
+
return {
id: String(item._id),
teamId: String(item.teamId),
@@ -201,29 +217,105 @@ export async function getChildAppPreviewNode({
hasTokenFee: false,
pluginOrder: 0
};
- } else {
+ }
+ // mcp tool
+ else if (source === PluginSourceEnum.mcp) {
+ const [parentId, toolName] = pluginId.split('/');
+ // 1. get parentApp
+ const item = await MongoApp.findById(parentId).lean();
+ if (!item) return Promise.reject(PluginErrEnum.unExist);
+
+ const version = await getAppVersionById({ appId: parentId, versionId, app: item });
+ const toolConfig = version.nodes[0].toolConfig?.mcpToolSet;
+ const tool = toolConfig?.toolList.find((item) => item.name === toolName);
+ if (!tool || !toolConfig) return Promise.reject(PluginErrEnum.unExist);
+
+ return {
+ avatar: item.avatar,
+ id: appId,
+ name: tool.name,
+ templateType: FlowNodeTemplateTypeEnum.tools,
+ workflow: {
+ nodes: [
+ getMCPToolRuntimeNode({
+ tool: {
+ description: tool.description,
+ inputSchema: tool.inputSchema,
+ name: tool.name
+ },
+ avatar: item.avatar,
+ parentId: item._id
+ })
+ ],
+ edges: []
+ },
+ version: '',
+ isLatestVersion: true
+ };
+ }
+ // 1. System Tools
+ // 2. System Plugins configured in Pro (has associatedPluginId)
+ else {
return getSystemPluginByIdAndVersionId(pluginId, versionId);
}
})();
- const { flowNodeType, nodeIOConfig } = await (async () => {
+ const { flowNodeType, nodeIOConfig } = await (async (): Promise<{
+ flowNodeType: FlowNodeTypeEnum;
+ nodeIOConfig: {
+ inputs: FlowNodeInputItemType[];
+ outputs: FlowNodeOutputItemType[];
+ toolConfig?: NodeToolConfigType;
+ showSourceHandle?: boolean;
+ showTargetHandle?: boolean;
+ };
+ }> => {
if (source === PluginSourceEnum.systemTool) {
+ // system Tool or Toolsets
+ const children = app.isFolder
+ ? (await getSystemTools()).filter((item) => item.parentId === pluginId)
+ : [];
+
return {
- flowNodeType: FlowNodeTypeEnum.tool,
+ flowNodeType: app.isFolder ? FlowNodeTypeEnum.toolSet : FlowNodeTypeEnum.tool,
nodeIOConfig: {
- inputs: app.inputs || [],
- outputs: app.outputs || [],
+ inputs: [
+ ...(app.inputList
+ ? [
+ {
+ key: NodeInputKeyEnum.systemInputConfig,
+ label: '',
+ renderTypeList: [FlowNodeInputTypeEnum.hidden],
+ inputList: app.inputList
+ }
+ ]
+ : []),
+ ...(app.inputs ?? [])
+ ],
+ outputs: app.outputs ?? [],
toolConfig: {
- systemTool: {
- toolId: app.id
- }
- }
+ ...(app.isFolder
+ ? {
+ systemToolSet: {
+ toolId: app.id,
+ toolList: children.map((item) => ({
+ toolId: item.id,
+ name: parseI18nString(item.name, lang),
+ description: parseI18nString(item.intro, lang)
+ }))
+ }
+ }
+ : { systemTool: { toolId: app.id } })
+ },
+ showSourceHandle: app.isFolder ? false : true,
+ showTargetHandle: app.isFolder ? false : true
}
};
}
// Plugin workflow
if (!!app.workflow.nodes.find((node) => node.flowNodeType === FlowNodeTypeEnum.pluginInput)) {
+ // plugin app
return {
flowNodeType: FlowNodeTypeEnum.pluginModule,
nodeIOConfig: pluginData2FlowNodeIO({ nodes: app.workflow.nodes })
@@ -235,6 +327,7 @@ export async function getChildAppPreviewNode({
!!app.workflow.nodes.find((node) => node.flowNodeType === FlowNodeTypeEnum.toolSet) &&
app.workflow.nodes.length === 1
) {
+ // mcp tools
return {
flowNodeType: FlowNodeTypeEnum.toolSet,
nodeIOConfig: toolSetData2FlowNodeIO({ nodes: app.workflow.nodes })
@@ -294,11 +387,15 @@ export async function getChildAppPreviewNode({
System plugin: plugin id
Personal plugin: Version id
*/
-export async function getChildAppRuntimeById(
- id: string,
- versionId?: string,
- lang: localeType = 'en'
-): Promise {
+export async function getChildAppRuntimeById({
+ id,
+ versionId,
+ lang = 'en'
+}: {
+ id: string;
+ versionId?: string;
+ lang?: localeType;
+}): Promise {
const app = await (async () => {
const { source, pluginId } = splitCombinePluginId(id);
@@ -351,6 +448,36 @@ export async function getChildAppRuntimeById(
};
}
+export async function getSystemPluginRuntimeNodeById({
+ pluginId,
+ name,
+ intro
+}: {
+ pluginId: string;
+ name: string;
+ intro: string;
+}): Promise {
+ const { source } = splitCombinePluginId(pluginId);
+ if (source === PluginSourceEnum.systemTool) {
+ const tool = await getSystemPluginByIdAndVersionId(pluginId);
+ return {
+ ...tool,
+ name,
+ intro,
+ inputs: tool.inputs ?? [],
+ outputs: tool.outputs ?? [],
+ flowNodeType: FlowNodeTypeEnum.tool,
+ nodeId: getNanoid(),
+ toolConfig: {
+ systemTool: {
+ toolId: pluginId
+ }
+ }
+ };
+ }
+ return Promise.reject(PluginErrEnum.unExist);
+}
+
const dbPluginFormat = (item: SystemPluginConfigSchemaType): SystemPluginTemplateItemType => {
const { name, avatar, intro, version, weight, templateType, associatedPluginId, userGuide } =
item.customConfig!;
@@ -405,11 +532,11 @@ export const refetchSystemPlugins = () => {
});
};
-export const getSystemPlugins = async (): Promise => {
+export const getSystemTools = async (): Promise => {
if (getCachedSystemPlugins().expires > Date.now() && isProduction) {
return getCachedSystemPlugins().data;
} else {
- const tools = await getSystemToolList();
+ const tools = await APIGetSystemToolList();
// 从数据库里加载插件配置进行替换
const systemPluginsArray = await MongoSystemPlugin.find({}).lean();
@@ -436,34 +563,21 @@ export const getSystemPlugins = async (): Promise tool.parentId === item.id),
- name: item.name,
- avatar: item.avatar,
- intro: item.intro,
- author: item.author,
- courseUrl: item.courseUrl,
showStatus: true,
- weight: item.weight,
- templateType: item.templateType,
- originCost: item.originCost,
- currentCost: item.currentCost,
- hasTokenFee: item.hasTokenFee,
- pluginOrder: item.pluginOrder,
-
workflow: {
nodes: [],
edges: []
},
versionList,
-
- inputList: inputs?.find((input) => input.key === NodeInputKeyEnum.systemInputConfig)
- ?.inputList as any,
+ inputs,
+ outputs,
+ inputList: item?.secretInputConfig,
hasSystemSecret: !!dbPluginConfig?.inputListVal
};
});
@@ -484,10 +598,10 @@ export const getSystemPlugins = async (): Promise => {
+export const getSystemToolById = async (id: string): Promise => {
const { source, pluginId } = splitCombinePluginId(id);
if (source === PluginSourceEnum.systemTool) {
- const tools = await getSystemPlugins();
+ const tools = await getSystemTools();
const tool = tools.find((item) => item.id === pluginId);
if (tool) {
return tool;
diff --git a/packages/service/core/app/plugin/utils.ts b/packages/service/core/app/plugin/utils.ts
index b813cf76e..848a92509 100644
--- a/packages/service/core/app/plugin/utils.ts
+++ b/packages/service/core/app/plugin/utils.ts
@@ -1,9 +1,9 @@
import { type ChatNodeUsageType } from '@fastgpt/global/support/wallet/bill/type';
import { type PluginRuntimeType } from '@fastgpt/global/core/app/plugin/type';
-import { splitCombinePluginId } from './controller';
import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants';
+import { splitCombinePluginId } from '@fastgpt/global/core/app/plugin/utils';
-/*
+/*
Plugin points calculation:
1. 系统插件/商业版插件:
- 有错误:返回 0
diff --git a/packages/service/core/app/tool/api.ts b/packages/service/core/app/tool/api.ts
index 1eda6f8c3..4e8592e7f 100644
--- a/packages/service/core/app/tool/api.ts
+++ b/packages/service/core/app/tool/api.ts
@@ -1,16 +1,9 @@
-import createClient, { RunToolWithStream } from '@fastgpt-sdk/plugin';
+import { RunToolWithStream } from '@fastgpt-sdk/plugin';
import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants';
+import { pluginClient, BASE_URL, TOKEN } from '../../../thirdProvider/fastgptPlugin';
-const BASE_URL = process.env.PLUGIN_BASE_URL || '';
-const TOKEN = process.env.PLUGIN_TOKEN || '';
-
-const client = createClient({
- baseUrl: BASE_URL,
- token: TOKEN
-});
-
-export async function getSystemToolList() {
- const res = await client.tool.list();
+export async function APIGetSystemToolList() {
+ const res = await pluginClient.tool.list();
if (res.status === 200) {
return res.body.map((item) => {
@@ -33,4 +26,4 @@ const runToolInstance = new RunToolWithStream({
baseUrl: BASE_URL,
token: TOKEN
});
-export const runSystemTool = runToolInstance.run.bind(runToolInstance);
+export const APIRunSystemTool = runToolInstance.run.bind(runToolInstance);
diff --git a/packages/service/core/app/utils.ts b/packages/service/core/app/utils.ts
index 123820106..37acfcbff 100644
--- a/packages/service/core/app/utils.ts
+++ b/packages/service/core/app/utils.ts
@@ -3,11 +3,13 @@ import { getEmbeddingModel } from '../ai/model';
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, splitCombinePluginId } from './plugin/controller';
+import { getChildAppPreviewNode } from './plugin/controller';
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';
+import { splitCombinePluginId } from '@fastgpt/global/core/app/plugin/utils';
+import type { localeType } from '@fastgpt/global/common/i18n/type';
export async function listAppDatasetDataByTeamIdAndDatasetIds({
teamId,
@@ -33,12 +35,14 @@ export async function rewriteAppWorkflowToDetail({
nodes,
teamId,
isRoot,
- ownerTmbId
+ ownerTmbId,
+ lang
}: {
nodes: StoreNodeItemType[];
teamId: string;
isRoot: boolean;
ownerTmbId: string;
+ lang?: localeType;
}) {
const datasetIdSet = new Set();
@@ -51,8 +55,9 @@ export async function rewriteAppWorkflowToDetail({
try {
const [preview] = await Promise.all([
getChildAppPreviewNode({
- appId: pluginId,
- versionId: node.version
+ appId: node.pluginId,
+ versionId: node.version,
+ lang
}),
...(source === PluginSourceEnum.personal
? [
@@ -80,6 +85,8 @@ export async function rewriteAppWorkflowToDetail({
node.hasTokenFee = preview.hasTokenFee;
node.hasSystemSecret = preview.hasSystemSecret;
+ node.toolConfig = preview.toolConfig;
+
// Latest version
if (!node.version) {
const inputsMap = new Map(node.inputs.map((item) => [item.key, item]));
diff --git a/packages/service/core/workflow/dispatch/ai/agent/index.ts b/packages/service/core/workflow/dispatch/ai/agent/index.ts
index f345d6d6f..867f2d275 100644
--- a/packages/service/core/workflow/dispatch/ai/agent/index.ts
+++ b/packages/service/core/workflow/dispatch/ai/agent/index.ts
@@ -361,7 +361,7 @@ const getMultiInput = async ({
};
};
-/*
+/*
Tool call, auth add file prompt to question。
Guide the LLM to call tool.
*/
diff --git a/packages/service/core/workflow/dispatch/child/runTool.ts b/packages/service/core/workflow/dispatch/child/runTool.ts
index ac8bfcb25..17e3875c9 100644
--- a/packages/service/core/workflow/dispatch/child/runTool.ts
+++ b/packages/service/core/workflow/dispatch/child/runTool.ts
@@ -10,14 +10,16 @@ import { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
import { MCPClient } from '../../../app/mcp';
import { getSecretValue } from '../../../../common/secret/utils';
import type { McpToolDataType } from '@fastgpt/global/core/app/mcpTools/type';
-import { runSystemTool } from '../../../app/tool/api';
+import { APIRunSystemTool } from '../../../app/tool/api';
import { MongoSystemPlugin } from '../../../app/plugin/systemPluginSchema';
import { SystemToolInputTypeEnum } from '@fastgpt/global/core/app/systemTool/constants';
import type { StoreSecretValueType } from '@fastgpt/global/common/secret/type';
-import { getSystemPluginById } from '../../../app/plugin/controller';
+import { getSystemToolById } from '../../../app/plugin/controller';
import { textAdaptGptResponse } from '@fastgpt/global/core/workflow/runtime/utils';
import { pushTrack } from '../../../../common/middle/tracks/utils';
import { getNodeErrResponse } from '../utils';
+import { splitCombinePluginId } from '@fastgpt/global/core/app/plugin/utils';
+import { getAppVersionById } from '../../../../core/app/version/controller';
type SystemInputConfigType = {
type: SystemToolInputTypeEnum;
@@ -52,8 +54,8 @@ export const dispatchRunTool = async (props: RunToolProps): Promise {
switch (params.system_input_config?.type) {
@@ -82,7 +84,7 @@ export const dispatchRunTool = async (props: RunToolProps): Promise {
- const variables = chatConfig?.variables || [];
- const variablesMap = variables.reduce>((acc, item) => {
- acc[item.key] = valueTypeFormat(item.defaultValue, item.valueType);
+ // Get global variables(Label -> key; Key -> key)
+ const globalVariables = chatConfig?.variables || [];
+ const variablesMap = globalVariables.reduce>((acc, item) => {
+ // API
+ if (variables[item.label] !== undefined) {
+ acc[item.key] = valueTypeFormat(variables[item.label], item.valueType);
+ }
+ // Web
+ else if (variables[item.key] !== undefined) {
+ acc[item.key] = valueTypeFormat(variables[item.key], item.valueType);
+ } else {
+ acc[item.key] = valueTypeFormat(item.defaultValue, item.valueType);
+ }
return acc;
}, {});
return {
...variablesMap,
+ // System var:
userId: uid,
appId: String(runningAppInfo.id),
chatId,
diff --git a/packages/service/core/workflow/dispatch/plugin/run.ts b/packages/service/core/workflow/dispatch/plugin/run.ts
index e9d490412..234bdf30a 100644
--- a/packages/service/core/workflow/dispatch/plugin/run.ts
+++ b/packages/service/core/workflow/dispatch/plugin/run.ts
@@ -1,4 +1,7 @@
-import { getPluginInputsFromStoreNodes } from '@fastgpt/global/core/app/plugin/utils';
+import {
+ getPluginInputsFromStoreNodes,
+ splitCombinePluginId
+} from '@fastgpt/global/core/app/plugin/utils';
import { chatValue2RuntimePrompt } from '@fastgpt/global/core/chat/adapt';
import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
@@ -15,9 +18,8 @@ import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { computedPluginUsage } from '../../../app/plugin/utils';
import { filterSystemVariables, getNodeErrResponse } from '../utils';
import { getPluginRunUserQuery } from '@fastgpt/global/core/workflow/utils';
-import type { NodeInputKeyEnum } from '@fastgpt/global/core/workflow/constants';
-import type { NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
-import { getChildAppRuntimeById, splitCombinePluginId } from '../../../app/plugin/controller';
+import type { NodeInputKeyEnum, NodeOutputKeyEnum } from '@fastgpt/global/core/workflow/constants';
+import { getChildAppRuntimeById } from '../../../app/plugin/controller';
import { dispatchWorkFlow } from '../index';
import { getUserChatInfoAndAuthTeamPoints } from '../../../../support/permission/auth/team';
import { dispatchRunTool } from '../child/runTool';
@@ -66,7 +68,7 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise {
};
};
-export const rewriteRuntimeWorkFlow = (
- nodes: RuntimeNodeItemType[],
- edges: RuntimeEdgeItemType[]
-) => {
+/**
+ * ToolSet node will be replaced by Children Tool Nodes.
+ * @param nodes
+ * @param edges
+ * @returns
+ */
+export const rewriteRuntimeWorkFlow = async ({
+ nodes,
+ edges
+}: {
+ nodes: RuntimeNodeItemType[];
+ edges: RuntimeEdgeItemType[];
+}) => {
const toolSetNodes = nodes.filter((node) => node.flowNodeType === FlowNodeTypeEnum.toolSet);
if (toolSetNodes.length === 0) {
@@ -165,35 +179,63 @@ export const rewriteRuntimeWorkFlow = (
for (const toolSetNode of toolSetNodes) {
nodeIdsToRemove.add(toolSetNode.nodeId);
- const toolSetValue = toolSetNode.inputs[0]?.value as McpToolSetDataType | undefined;
-
- if (!toolSetValue) continue;
-
- const toolList = toolSetValue.toolList;
- const url = toolSetValue.url;
- const headerSecret = toolSetValue.headerSecret;
+ const systemToolId = toolSetNode.toolConfig?.systemToolSet?.toolId;
+ const mcpToolsetVal = toolSetNode.toolConfig?.mcpToolSet ?? toolSetNode.inputs[0].value;
const incomingEdges = edges.filter((edge) => edge.target === toolSetNode.nodeId);
-
- for (const tool of toolList) {
- const newToolNode = getMCPToolRuntimeNode({
- avatar: toolSetNode.avatar,
- tool,
- url,
- headerSecret
- });
-
- nodes.push({ ...newToolNode, name: `${toolSetNode.name} / ${tool.name}` });
-
+ const pushEdges = (nodeId: string) => {
for (const inEdge of incomingEdges) {
edges.push({
source: inEdge.source,
- target: newToolNode.nodeId,
+ target: nodeId,
sourceHandle: inEdge.sourceHandle,
targetHandle: 'selectedTools',
status: inEdge.status
});
}
+ };
+
+ // systemTool
+ if (systemToolId) {
+ const toolsetInputConfig = toolSetNode.inputs.find(
+ (item) => item.key === NodeInputKeyEnum.systemInputConfig
+ );
+ const tools = await getSystemTools();
+ const children = tools.filter((item) => item.parentId === systemToolId);
+ for (const child of children) {
+ const toolListItem = toolSetNode.toolConfig?.systemToolSet?.toolList.find(
+ (item) => item.toolId === child.id
+ )!;
+ const newNode = await getSystemPluginRuntimeNodeById({
+ pluginId: child.id,
+ name: toolListItem?.name,
+ intro: toolListItem?.description
+ });
+ const newNodeInputConfig = newNode.inputs.find(
+ (item) => item.key === NodeInputKeyEnum.systemInputConfig
+ );
+ if (newNodeInputConfig) {
+ newNodeInputConfig.value = toolsetInputConfig?.value;
+ }
+ nodes.push(newNode);
+ pushEdges(newNode.nodeId);
+ }
+ } else if (mcpToolsetVal) {
+ const app = await MongoApp.findOne({ _id: toolSetNode.pluginId }).lean();
+ if (!app) continue;
+ const toolList = await getMCPChildren(app);
+
+ for (const tool of toolList) {
+ const newToolNode = getMCPToolRuntimeNode({
+ avatar: toolSetNode.avatar,
+ tool,
+ // New ?? Old
+ parentId: mcpToolsetVal.toolId ?? toolSetNode.pluginId
+ });
+
+ nodes.push({ ...newToolNode, name: `${toolSetNode.name}/${tool.name}` });
+ pushEdges(newToolNode.nodeId);
+ }
}
}
diff --git a/packages/service/package.json b/packages/service/package.json
index 17772a8ce..a44869105 100644
--- a/packages/service/package.json
+++ b/packages/service/package.json
@@ -3,7 +3,7 @@
"version": "1.0.0",
"type": "module",
"dependencies": {
- "@fastgpt-sdk/plugin": "^0.1.2",
+ "@fastgpt-sdk/plugin": "^0.1.4",
"@fastgpt/global": "workspace:*",
"@modelcontextprotocol/sdk": "^1.12.1",
"@node-rs/jieba": "2.0.1",
diff --git a/packages/service/support/permission/app/auth.ts b/packages/service/support/permission/app/auth.ts
index f60cb8e0b..26d81522c 100644
--- a/packages/service/support/permission/app/auth.ts
+++ b/packages/service/support/permission/app/auth.ts
@@ -10,10 +10,10 @@ import { AppPermission } from '@fastgpt/global/support/permission/app/controller
import { type PermissionValueType } from '@fastgpt/global/support/permission/type';
import { AppFolderTypeList } from '@fastgpt/global/core/app/constants';
import { type ParentIdType } from '@fastgpt/global/common/parentFolder/type';
-import { splitCombinePluginId } from '../../../core/app/plugin/controller';
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';
+import { splitCombinePluginId } from '@fastgpt/global/core/app/plugin/utils';
export const authPluginByTmbId = async ({
tmbId,
diff --git a/packages/service/support/permission/teamLimit.ts b/packages/service/support/permission/teamLimit.ts
index ba172d0f3..145d0d90c 100644
--- a/packages/service/support/permission/teamLimit.ts
+++ b/packages/service/support/permission/teamLimit.ts
@@ -46,7 +46,7 @@ export const checkTeamAppLimit = async (teamId: string, amount = 1) => {
MongoApp.countDocuments({
teamId,
type: {
- $in: [AppTypeEnum.simple, AppTypeEnum.workflow, AppTypeEnum.plugin, AppTypeEnum.tool]
+ $in: [AppTypeEnum.simple, AppTypeEnum.workflow, AppTypeEnum.plugin, AppTypeEnum.toolSet]
}
})
]);
@@ -59,7 +59,7 @@ export const checkTeamAppLimit = async (teamId: string, amount = 1) => {
if (global?.licenseData?.maxApps && typeof global?.licenseData?.maxApps === 'number') {
const totalApps = await MongoApp.countDocuments({
type: {
- $in: [AppTypeEnum.simple, AppTypeEnum.workflow, AppTypeEnum.plugin, AppTypeEnum.tool]
+ $in: [AppTypeEnum.simple, AppTypeEnum.workflow, AppTypeEnum.plugin, AppTypeEnum.toolSet]
}
});
if (totalApps >= global.licenseData.maxApps) {
diff --git a/packages/service/thirdProvider/doc2x/index.ts b/packages/service/thirdProvider/doc2x/index.ts
index 0e33c0ea2..998e074d9 100644
--- a/packages/service/thirdProvider/doc2x/index.ts
+++ b/packages/service/thirdProvider/doc2x/index.ts
@@ -139,17 +139,27 @@ export const useDoc2xServer = ({ apiKey }: { apiKey: string }) => {
// Finifsh
if (result_data.status === 'success') {
+ const cleanedText = result_data.result.pages
+ .map((page) => page.md)
+ .join('')
+ .replace(/\\[\(\)]/g, '$')
+ .replace(/\\[\[\]]/g, '$$')
+ .replace(/ ]*)?(?:\s*\/>|>)/g, '')
+ .replace(//g, '')
+ .replace(//g, '')
+ .replace(//g, '')
+ .replace(//g, '')
+ .replace(/\$(.+?)\s+\\tag\{(.+?)\}\$/g, '$$$1 \\qquad \\qquad ($2)$$')
+ .replace(/\\text\{([^}]*?)(\b\w+)_(\w+\b)([^}]*?)\}/g, '\\text{$1$2\\_$3$4}');
+ const remainingTags = cleanedText.match(//g);
+ if (remainingTags) {
+ addLog.warn(`[Doc2x] Remaining dirty tags after cleaning:`, {
+ count: remainingTags.length,
+ tags: remainingTags.slice(0, 3)
+ });
+ }
return {
- text: result_data.result.pages
- .map((page) => page.md)
- .join('')
- .replace(/\\[\(\)]/g, '$')
- .replace(/\\[\[\]]/g, '$$')
- .replace(/ ]*)?(?:\s*\/>|>)/g, '')
- .replace(//g, '')
- .replace(//g, '')
- .replace(/\$(.+?)\s+\\tag\{(.+?)\}\$/g, '$$$1 \\qquad \\qquad ($2)$$')
- .replace(/\\text\{([^}]*?)(\b\w+)_(\w+\b)([^}]*?)\}/g, '\\text{$1$2\\_$3$4}'),
+ text: cleanedText,
pages: result_data.result.pages.length
};
}
diff --git a/packages/service/thirdProvider/fastgptPlugin/index.ts b/packages/service/thirdProvider/fastgptPlugin/index.ts
new file mode 100644
index 000000000..3c6ab5127
--- /dev/null
+++ b/packages/service/thirdProvider/fastgptPlugin/index.ts
@@ -0,0 +1,9 @@
+import createClient from '@fastgpt-sdk/plugin';
+
+export const BASE_URL = process.env.PLUGIN_BASE_URL || '';
+export const TOKEN = process.env.PLUGIN_TOKEN || '';
+
+export const pluginClient = createClient({
+ baseUrl: BASE_URL,
+ token: TOKEN
+});
diff --git a/packages/service/worker/readFile/extension/xlsx.ts b/packages/service/worker/readFile/extension/xlsx.ts
index 34a0c203f..594986c87 100644
--- a/packages/service/worker/readFile/extension/xlsx.ts
+++ b/packages/service/worker/readFile/extension/xlsx.ts
@@ -20,18 +20,16 @@ export const readXlsxRawText = async ({
const rawText = format2Csv.map((item) => item.csvText).join('\n');
- const formatText = format2Csv
- .map((item) => {
- const csvArr = Papa.parse(item.csvText).data as string[][];
- const header = csvArr[0];
-
+ const formatText = result
+ .map(({ data }) => {
+ const header = data[0];
if (!header) return;
const formatText = `| ${header.join(' | ')} |
| ${header.map(() => '---').join(' | ')} |
-${csvArr
+${data
.slice(1)
- .map((row) => `| ${row.map((item) => item.replace(/\n/g, '\\n')).join(' | ')} |`)
+ .map((row) => `| ${row.map((cell) => String(cell).replace(/\n/g, '\\n')).join(' | ')} |`)
.join('\n')}`;
return formatText;
diff --git a/packages/service/worker/text2Chunks/index.ts b/packages/service/worker/text2Chunks/index.ts
index 9a9fc1147..6637bd09d 100644
--- a/packages/service/worker/text2Chunks/index.ts
+++ b/packages/service/worker/text2Chunks/index.ts
@@ -2,6 +2,7 @@ import { parentPort } from 'worker_threads';
import type { SplitProps } from '@fastgpt/global/common/string/textSplitter';
import { splitText2Chunks } from '@fastgpt/global/common/string/textSplitter';
import { workerResponse } from '../controller';
+import { delay } from '@fastgpt/global/common/system/utils';
parentPort?.on('message', async (props: SplitProps) => {
const result = splitText2Chunks(props);
diff --git a/packages/web/components/common/DateRangePicker/index.tsx b/packages/web/components/common/DateRangePicker/index.tsx
index e39daa7ed..f21a4fa5b 100644
--- a/packages/web/components/common/DateRangePicker/index.tsx
+++ b/packages/web/components/common/DateRangePicker/index.tsx
@@ -1,5 +1,6 @@
import React, { useState, useMemo, useRef, useEffect } from 'react';
-import { Box, Card, Flex, useTheme, useOutsideClick, Button } from '@chakra-ui/react';
+import type { BoxProps } from '@chakra-ui/react';
+import { Box, Card, Flex, useOutsideClick, Button } from '@chakra-ui/react';
import { addDays, format } from 'date-fns';
import { DayPicker } from 'react-day-picker';
import 'react-day-picker/dist/style.css';
@@ -15,21 +16,23 @@ export type DateRangeType = {
const DateRangePicker = ({
onChange,
onSuccess,
- position = 'bottom',
+ popPosition = 'bottom',
defaultDate = {
from: addDays(new Date(), -30),
to: new Date()
},
- dateRange
+ dateRange,
+ formLabel,
+ ...props
}: {
onChange?: (date: DateRangeType) => void;
onSuccess?: (date: DateRangeType) => void;
- position?: 'bottom' | 'top';
+ popPosition?: 'bottom' | 'top';
defaultDate?: DateRangeType;
dateRange?: DateRangeType;
-}) => {
+ formLabel?: string;
+} & BoxProps) => {
const { t } = useTranslation();
- const theme = useTheme();
const OutRangeRef = useRef(null);
const [range, setRange] = useState(defaultDate);
const [showSelected, setShowSelected] = useState(false);
@@ -42,9 +45,9 @@ const DateRangePicker = ({
const formatSelected = useMemo(() => {
if (range?.from && range.to) {
- return `${format(range.from, 'y-MM-dd')} ~ ${format(range.to, 'y-MM-dd')}`;
+ return `${format(range.from, 'y/MM/dd')} - ${format(range.to, 'y/MM/dd')}`;
}
- return `${format(new Date(), 'y-MM-dd')} ~ ${format(new Date(), 'y-MM-dd')}`;
+ return `${format(new Date(), 'y/MM/dd')} - ${format(new Date(), 'y/MM/dd')}`;
}, [range]);
useOutsideClick({
@@ -57,19 +60,30 @@ const DateRangePicker = ({
return (
setShowSelected(true)}
+ alignItems={'center'}
+ {...props}
>
-
+ {formLabel && (
+ <>
+
+ {formLabel}
+
+
+ >
+ )}
+
{formatSelected}
-
+ {!formLabel && }
{showSelected && (
import('./icons/union.svg'),
user: () => import('./icons/user.svg'),
visible: () => import('./icons/visible.svg'),
+ invisible: () => import('./icons/invisible.svg'),
wx: () => import('./icons/wx.svg')
};
diff --git a/packages/web/components/common/Icon/icons/invisible.svg b/packages/web/components/common/Icon/icons/invisible.svg
new file mode 100644
index 000000000..a1349ce3b
--- /dev/null
+++ b/packages/web/components/common/Icon/icons/invisible.svg
@@ -0,0 +1,7 @@
+
\ No newline at end of file
diff --git a/packages/web/components/common/Icon/icons/visible.svg b/packages/web/components/common/Icon/icons/visible.svg
index 74a44b850..933c63f5d 100644
--- a/packages/web/components/common/Icon/icons/visible.svg
+++ b/packages/web/components/common/Icon/icons/visible.svg
@@ -1,3 +1,3 @@
-
+
\ No newline at end of file
diff --git a/packages/web/components/common/MySelect/MultipleSelect.tsx b/packages/web/components/common/MySelect/MultipleSelect.tsx
index e57d2c01b..ff2ef80c6 100644
--- a/packages/web/components/common/MySelect/MultipleSelect.tsx
+++ b/packages/web/components/common/MySelect/MultipleSelect.tsx
@@ -1,9 +1,11 @@
+import type { FlexProps } from '@chakra-ui/react';
import {
Box,
Button,
type ButtonProps,
Checkbox,
Flex,
+ Input,
Menu,
MenuButton,
MenuItem,
@@ -11,13 +13,27 @@ import {
MenuList,
useDisclosure
} from '@chakra-ui/react';
-import React, { useCallback, useMemo, useRef, useState } from 'react';
+import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import MyTag from '../Tag/index';
import MyIcon from '../Icon';
import MyAvatar from '../Avatar';
import { useTranslation } from 'next-i18next';
import type { useScrollPagination } from '../../../hooks/useScrollPagination';
import MyDivider from '../MyDivider';
+import { shadowLight } from '../../../styles/theme';
+
+const menuItemStyles: MenuItemProps = {
+ borderRadius: 'sm',
+ py: 2,
+ display: 'flex',
+ alignItems: 'center',
+ _hover: {
+ backgroundColor: 'myGray.100'
+ },
+ _notLast: {
+ mb: 2
+ }
+};
export type SelectProps = {
list: {
@@ -30,19 +46,25 @@ export type SelectProps = {
setIsSelectAll?: React.Dispatch>;
placeholder?: string;
- maxH?: number;
itemWrap?: boolean;
onSelect: (val: T[]) => void;
closeable?: boolean;
isDisabled?: boolean;
ScrollData?: ReturnType['ScrollData'];
+
+ formLabel?: string;
+ formLabelFontSize?: string;
+
+ inputValue?: string;
+ setInputValue?: (val: string) => void;
+
+ tagStyle?: FlexProps;
} & Omit;
const MultipleSelect = ({
value = [],
placeholder,
list = [],
- maxH = 400,
onSelect,
closeable = false,
itemWrap = true,
@@ -50,27 +72,92 @@ const MultipleSelect = ({
isSelectAll,
setIsSelectAll,
isDisabled = false,
+
+ formLabel,
+ formLabelFontSize = 'sm',
+
+ inputValue,
+ setInputValue,
+
+ tagStyle,
...props
}: SelectProps) => {
const ref = useRef(null);
+ const SearchInputRef = useRef(null);
+ const tagsContainerRef = useRef(null);
+
const { t } = useTranslation();
const { isOpen, onOpen, onClose } = useDisclosure();
- const menuItemStyles: MenuItemProps = {
- borderRadius: 'sm',
- py: 2,
- display: 'flex',
- alignItems: 'center',
- _hover: {
- backgroundColor: 'myGray.100'
- },
- _notLast: {
- mb: 2
- }
+ const canInput = setInputValue !== undefined;
+
+ type SelectedItemType = {
+ icon?: string;
+ label: string | React.ReactNode;
+ value: T;
};
+ const [visibleItems, setVisibleItems] = useState([]);
+ const [overflowItems, setOverflowItems] = useState([]);
+
+ const selectedItems = useMemo(() => {
+ return value.map((val) => {
+ const listItem = list.find((item) => item.value === val);
+ return listItem || { value: val, label: String(val) };
+ });
+ }, [value, list]);
+
+ const handleKeyDown = useCallback(
+ (e: React.KeyboardEvent) => {
+ if (e.key === 'Backspace' && (!inputValue || inputValue === '')) {
+ const newValue = [...value];
+ newValue.pop();
+ onSelect(newValue);
+ }
+ },
+ [inputValue, value, isSelectAll, onSelect]
+ );
+ useEffect(() => {
+ if (!isOpen) {
+ setInputValue?.('');
+ }
+ }, [isOpen]);
+
+ useEffect(() => {
+ const getWidth = (w: any) =>
+ typeof w === 'number' ? w : typeof w === 'string' ? parseInt(w) : 0;
+
+ const totalWidth = getWidth(props.w) || 200;
+ const tagWidth = getWidth(tagStyle?.w) || 60;
+ const formLabelWidth = formLabel ? formLabel.length * 8 + 20 : 0;
+ const availableWidth = totalWidth - formLabelWidth - 40;
+ const overflowWidth = 30;
+
+ if (availableWidth <= 0) {
+ setVisibleItems(selectedItems.length > 0 ? [selectedItems[0]] : []);
+ setOverflowItems(selectedItems.slice(1));
+ return;
+ }
+
+ const { count } = selectedItems.reduce(
+ (acc, item, i) => {
+ const remain = selectedItems.length - i - 1;
+ const needOverflow = remain > 0 ? overflowWidth : 0;
+ if (acc.used + tagWidth + needOverflow <= availableWidth) {
+ return {
+ used: acc.used + tagWidth,
+ count: i + 1
+ };
+ }
+ return acc;
+ },
+ { used: 0, count: 0 }
+ );
+ setVisibleItems(selectedItems.slice(0, count));
+ setOverflowItems(selectedItems.slice(count));
+ }, [selectedItems, isOpen, props.w, tagStyle, formLabel]);
+
const onclickItem = useCallback(
(val: T) => {
- // 全选状态下,value 实际上上空。
if (isSelectAll) {
onSelect(list.map((item) => item.value).filter((i) => i !== val));
setIsSelectAll?.(false);
@@ -141,12 +228,11 @@ const MultipleSelect = ({
>
({
{...props}
{...(isOpen && !isDisabled
? {
- boxShadow: '0px 0px 4px #A8DBFF',
- borderColor: 'primary.500',
+ boxShadow: shadowLight,
+ borderColor: 'primary.600 !important',
bg: 'white'
}
: {})}
>
- {value.length === 0 && placeholder ? (
-
- {placeholder}
-
- ) : (
-
+
+ {formLabel && (
+
+
+ {formLabel}
+
+
+
+ )}
+ {value.length === 0 && placeholder ? (
+
+ {placeholder}
+
+ ) : (
- {isSelectAll ? (
-
- {t('common:All')}
-
- ) : (
- list
- .filter((item) => value.includes(item.value))
- .map((item, i) => (
-
- {item.label}
- {closeable && (
- {
- e.stopPropagation();
- e.preventDefault();
- onclickItem(item.value);
- }}
- />
- )}
-
- ))
+ {(!isOpen || !canInput) &&
+ (isSelectAll ? (
+
+ {t('common:All')}
+
+ ) : (
+ <>
+ {visibleItems.map((item, i) => (
+
+ {item.label}
+ {closeable && (
+ {
+ e.stopPropagation();
+ e.preventDefault();
+ onclickItem(item.value);
+ }}
+ />
+ )}
+
+ ))}
+ {overflowItems.length > 0 && (
+
+ +{overflowItems.length}
+
+ )}
+ >
+ ))}
+ {canInput && isOpen && (
+ setInputValue?.(e.target.value)}
+ onKeyDown={handleKeyDown}
+ ref={SearchInputRef}
+ autoFocus
+ onBlur={() => {
+ setTimeout(() => {
+ SearchInputRef?.current?.focus();
+ }, 0);
+ }}
+ h={6}
+ variant={'unstyled'}
+ border={'none'}
+ />
)}
-
-
- )}
+ )}
+
+
({
- {ScrollData ? {ListRender} : ListRender}
+ {ScrollData ? {ListRender} : ListRender}
diff --git a/packages/web/hooks/useSafeTranslation.ts b/packages/web/hooks/useSafeTranslation.ts
index 806a92f19..a3f90efa7 100644
--- a/packages/web/hooks/useSafeTranslation.ts
+++ b/packages/web/hooks/useSafeTranslation.ts
@@ -1,7 +1,7 @@
import { useTranslation as useNextTranslation } from 'next-i18next';
import { I18N_NAMESPACES_MAP } from '../i18n/constants';
-export function useTranslation() {
+export function useSafeTranslation() {
const { t: originalT, ...rest } = useNextTranslation();
const t = (key: string | undefined, ...args: any[]): string => {
diff --git a/packages/web/i18n/en/app.json b/packages/web/i18n/en/app.json
index 07d008c3f..d6d12a739 100644
--- a/packages/web/i18n/en/app.json
+++ b/packages/web/i18n/en/app.json
@@ -90,10 +90,29 @@
"llm_use_vision": "Vision",
"llm_use_vision_tip": "After clicking on the model selection, you can see whether the model supports image recognition and the ability to control whether to start image recognition. \nAfter starting image recognition, the model will read the image content in the file link, and if the user question is less than 500 words, it will automatically parse the image in the user question.",
"logs_chat_user": "user",
+ "logs_date": "date",
"logs_empty": "No logs yet~",
+ "logs_error_count": "Error Count",
"logs_export_confirm_tip": "There are currently {{total}} conversation records, and each conversation can export up to 100 latest messages. \nConfirm export?",
"logs_export_title": "Time, source, user, contact, title, total number of messages, user good feedback, user bad feedback, custom feedback, labeled answers, conversation details",
+ "logs_key_config": "Field Configuration",
+ "logs_keys_annotatedCount": "Annotated Answer Count",
+ "logs_keys_createdTime": "Created Time",
+ "logs_keys_customFeedback": "Custom Feedback",
+ "logs_keys_errorCount": "Error Count",
+ "logs_keys_feedback": "User Feedback",
+ "logs_keys_lastConversationTime": "Last Conversation Time",
+ "logs_keys_messageCount": "Message Count",
+ "logs_keys_points": "Points Consumed",
+ "logs_keys_responseTime": "Average Response Time",
+ "logs_keys_sessionId": "Session ID",
+ "logs_keys_source": "Source",
+ "logs_keys_title": "Title",
+ "logs_keys_user": "User",
"logs_message_total": "Total Messages",
+ "logs_points": "Points Consumed",
+ "logs_response_time": "Average Response Time",
+ "logs_search_chat": "Search for session title or session ID",
"logs_source": "source",
"logs_title": "Title",
"look_ai_point_price": "View all model billing standards",
@@ -134,6 +153,7 @@
"question_guide_tip": "After the conversation, 3 guiding questions will be generated for you.",
"reasoning_response": "Output thinking",
"response_format": "Response format",
+ "save_team_app_log_keys": "Save as team configuration",
"saved_success": "Saved successfully! \nTo use this version externally, click Save and Publish",
"search_app": "Search apps",
"search_tool": "Search Tools",
@@ -147,7 +167,10 @@
"stop_sign_placeholder": "Multiple serial numbers are separated by |, for example: aaa|stop",
"stream_response": "Stream",
"stream_response_tip": "Turning this switch off forces the model to use non-streaming mode and will not output content directly. \nIn the output of the AI reply, the content output by this model can be obtained for secondary processing.",
+ "sync_log_keys_popover_text": "The current field configuration is only valid for individuals. Do you need to save it to the team configuration?",
+ "sync_team_app_log_keys": "Restore to team configuration",
"system_secret": "System secret",
+ "systemval_conflict_globalval": "The variable name conflicts with the system variable, please use other variable names",
"team_tags_set": "Team tags",
"temperature": "Temperature",
"temperature_tip": "Range 0~10. \nThe larger the value, the more divergent the model’s answer is; the smaller the value, the more rigorous the answer.",
@@ -229,6 +252,8 @@
"upload_file_max_amount_tip": "Maximum number of files uploaded in a single round of conversation",
"variable.select type_desc": "You can define a global variable that does not need to be filled in by the user.\n\nThe value of this variable can come from the API interface, the Query of the shared link, or assigned through the [Variable Update] module.",
"variable.textarea_type_desc": "Allows users to input up to 4000 characters in the dialogue box.",
+ "variable_name_required": "Required variable name",
+ "variable_repeat": "This variable name has been occupied and cannot be used",
"version.Revert success": "Revert Successful",
"version_back": "Revert to Original State",
"version_copy": "Duplicate",
diff --git a/packages/web/i18n/en/common.json b/packages/web/i18n/en/common.json
index 3baeb4025..afa22e52c 100644
--- a/packages/web/i18n/en/common.json
+++ b/packages/web/i18n/en/common.json
@@ -114,6 +114,8 @@
"can_copy_content_tip": "It is not possible to copy automatically using the browser, please manually copy the following content",
"chart_mode_cumulative": "Cumulative",
"chart_mode_incremental": "Incremental",
+ "chat": "Session",
+ "chat_chatId": "Session Id: {{chatId}}",
"choosable": "Choosable",
"chose_condition": "Choose Condition",
"chosen": "Chosen",
@@ -679,7 +681,6 @@
"core.module.variable.add option": "Add Option",
"core.module.variable.input type": "Text",
"core.module.variable.key": "Variable Key",
- "core.module.variable.key already exists": "Key Already Exists",
"core.module.variable.key is required": "Variable Key is Required",
"core.module.variable.select type": "Dropdown Single Select",
"core.module.variable.text max length": "Max Length",
@@ -878,6 +879,7 @@
"max_quote_tokens": "Quote cap",
"max_quote_tokens_tips": "The maximum number of tokens in a single search, about 1 character in Chinese = 1.7 tokens, and about 1 character in English = 1 token",
"mcp_server": "MCP Services",
+ "member": "member",
"min_similarity": "lowest correlation",
"min_similarity_tip": "The relevance of different index models is different. Please select the appropriate value through search testing. \nWhen using Result Rearrange , use the rearranged results for filtering.",
"model.billing": "Billing",
diff --git a/packages/web/i18n/zh-CN/app.json b/packages/web/i18n/zh-CN/app.json
index 7e5514546..6b62f5cf9 100644
--- a/packages/web/i18n/zh-CN/app.json
+++ b/packages/web/i18n/zh-CN/app.json
@@ -90,10 +90,29 @@
"llm_use_vision": "图片识别",
"llm_use_vision_tip": "点击模型选择后,可以看到模型是否支持图片识别以及控制是否启动图片识别的能力。启动图片识别后,模型会读取文件链接里图片内容,并且如果用户问题少于 500 字,会自动解析用户问题中的图片。",
"logs_chat_user": "使用者",
+ "logs_date": "日期",
"logs_empty": "还没有日志噢~",
+ "logs_error_count": "报错数量",
"logs_export_confirm_tip": "当前共有 {{total}} 条对话记录,每条对话最多可导出最新 100 条消息。确认导出?",
"logs_export_title": "时间,来源,使用者,联系方式,标题,消息总数,用户赞同反馈,用户反对反馈,自定义反馈,标注答案,对话详情",
+ "logs_key_config": "字段配置",
+ "logs_keys_annotatedCount": "标注答案数量",
+ "logs_keys_createdTime": "创建时间",
+ "logs_keys_customFeedback": "自定义反馈",
+ "logs_keys_errorCount": "报错数量",
+ "logs_keys_feedback": "用户反馈",
+ "logs_keys_lastConversationTime": "上次对话时间",
+ "logs_keys_messageCount": "消息总数",
+ "logs_keys_points": "积分消耗",
+ "logs_keys_responseTime": "平均响应时长",
+ "logs_keys_sessionId": "会话 ID",
+ "logs_keys_source": "来源",
+ "logs_keys_title": "标题",
+ "logs_keys_user": "使用者",
"logs_message_total": "消息总数",
+ "logs_points": "积分消耗",
+ "logs_response_time": "平均响应时长",
+ "logs_search_chat": "搜索会话标题或会话 ID",
"logs_source": "来源",
"logs_title": "标题",
"look_ai_point_price": "查看所有模型计费标准",
@@ -134,6 +153,7 @@
"question_guide_tip": "对话结束后,会为你生成 3 个引导性问题。",
"reasoning_response": "输出思考",
"response_format": "回复格式",
+ "save_team_app_log_keys": "保存为团队配置",
"saved_success": "保存成功!如需在外部使用该版本,请点击“保存并发布”",
"search_app": "搜索应用",
"search_tool": "搜索工具",
@@ -147,7 +167,10 @@
"stop_sign_placeholder": "多个序列号通过 | 隔开,例如:aaa|stop",
"stream_response": "流输出",
"stream_response_tip": "关闭该开关,可以强制模型使用非流模式,并且不会直接进行内容输出。可以在 AI 回复的输出中,获取本次模型输出的内容进行二次处理。",
+ "sync_log_keys_popover_text": "当前字段配置仅对个人生效,是否需要保存至团队配置?",
+ "sync_team_app_log_keys": "还原成团队配置",
"system_secret": "系统密钥",
+ "systemval_conflict_globalval": "变量名与系统变量有冲突,请使用其他变量名",
"team_tags_set": "团队标签",
"temperature": "温度",
"temperature_tip": "范围 0~10。值越大,代表模型回答越发散;值越小,代表回答越严谨。",
@@ -229,6 +252,8 @@
"upload_file_max_amount_tip": "单轮对话中最大上传文件数量",
"variable.select type_desc": "可以为工作流定义全局变量,常用临时缓存。赋值的方式包括:\n1. 从对话页面的 query 参数获取。\n2. 通过 API 的 variables 对象传递。\n3. 通过【变量更新】节点进行赋值。",
"variable.textarea_type_desc": "允许用户最多输入4000字的对话框。",
+ "variable_name_required": "变量名必填",
+ "variable_repeat": "该变量名已被占用,无法使用",
"version.Revert success": "回滚成功",
"version_back": "回到初始状态",
"version_copy": "副本",
diff --git a/packages/web/i18n/zh-CN/common.json b/packages/web/i18n/zh-CN/common.json
index b86a7876d..7b6d158e7 100644
--- a/packages/web/i18n/zh-CN/common.json
+++ b/packages/web/i18n/zh-CN/common.json
@@ -114,6 +114,8 @@
"can_copy_content_tip": "无法使用浏览器自动复制,请手动复制下面内容",
"chart_mode_cumulative": "累积",
"chart_mode_incremental": "分时",
+ "chat": "会话",
+ "chat_chatId": "会话Id: {{chatId}}",
"choosable": "可选",
"chose_condition": "选择条件",
"chosen": "已选",
@@ -679,7 +681,6 @@
"core.module.variable.add option": "添加选项",
"core.module.variable.input type": "文本",
"core.module.variable.key": "变量 key",
- "core.module.variable.key already exists": "Key 已经存在",
"core.module.variable.key is required": "变量 key 是必须的",
"core.module.variable.select type": "下拉单选",
"core.module.variable.text max length": "最大长度",
@@ -878,6 +879,7 @@
"max_quote_tokens": "引用上限",
"max_quote_tokens_tips": "单次搜索最大的 token 数量,中文约 1 字=1.7 tokens,英文约 1 字=1 token",
"mcp_server": "MCP 服务",
+ "member": "成员",
"min_similarity": "最低相关度",
"min_similarity_tip": "不同索引模型的相关度有区别,请通过搜索测试来选择合适的数值。使用 结果重排 时,使用重排结果进行过滤。",
"model.billing": "模型计费",
diff --git a/packages/web/i18n/zh-Hant/app.json b/packages/web/i18n/zh-Hant/app.json
index d3ae7bb86..cbe8dcc2b 100644
--- a/packages/web/i18n/zh-Hant/app.json
+++ b/packages/web/i18n/zh-Hant/app.json
@@ -90,10 +90,29 @@
"llm_use_vision": "圖片辨識",
"llm_use_vision_tip": "點選模型選擇後,可以看到模型是否支援圖片辨識以及控制是否啟用圖片辨識的功能。啟用圖片辨識後,模型會讀取檔案連結中的圖片內容,並且如果使用者問題少於 500 字,會自動解析使用者問題中的圖片。",
"logs_chat_user": "使用者",
+ "logs_date": "日期",
"logs_empty": "還沒有紀錄喔~",
+ "logs_error_count": "錯誤數量",
"logs_export_confirm_tip": "當前共有 {{total}} 條對話記錄,每條對話最多可導出最新 100 條消息。\n確認導出?",
"logs_export_title": "時間,來源,使用者,聯絡方式,標題,訊息總數,使用者贊同回饋,使用者反對回饋,自定義回饋,標註答案,對話詳細資訊",
+ "logs_key_config": "字段配置",
+ "logs_keys_annotatedCount": "標記答案數量",
+ "logs_keys_createdTime": "建立時間",
+ "logs_keys_customFeedback": "自訂回饋",
+ "logs_keys_errorCount": "錯誤數量",
+ "logs_keys_feedback": "使用者回饋",
+ "logs_keys_lastConversationTime": "上次對話時間",
+ "logs_keys_messageCount": "訊息總數",
+ "logs_keys_points": "積分消耗",
+ "logs_keys_responseTime": "平均回應時長",
+ "logs_keys_sessionId": "會話 ID",
+ "logs_keys_source": "來源",
+ "logs_keys_title": "標題",
+ "logs_keys_user": "使用者",
"logs_message_total": "訊息總數",
+ "logs_points": "積分消耗",
+ "logs_response_time": "平均回應時長",
+ "logs_search_chat": "搜索會話標題或會話 ID",
"logs_source": "來源",
"logs_title": "標題",
"look_ai_point_price": "檢視所有模型計費標準",
@@ -134,6 +153,7 @@
"question_guide_tip": "對話結束後,會為你產生 3 個引導性問題。",
"reasoning_response": "輸出思考",
"response_format": "回覆格式",
+ "save_team_app_log_keys": "保存為團隊配置",
"saved_success": "儲存成功!\n如需在外部使用該版本,請點選“儲存並發布”",
"search_app": "搜尋應用程式",
"search_tool": "搜索工具",
@@ -147,7 +167,10 @@
"stop_sign_placeholder": "多個序列號透過 | 隔開,例如:aaa|stop",
"stream_response": "流輸出",
"stream_response_tip": "關閉該開關,可以強制模型使用非流模式,並且不會直接進行內容輸出。\n可在 AI 回覆的輸出中,取得本次模型輸出的內容進行二次處理。",
+ "sync_log_keys_popover_text": "當前字段配置僅對個人生效,是否需要保存至團隊配置?",
+ "sync_team_app_log_keys": "還原成團隊配置",
"system_secret": "系統密鑰",
+ "systemval_conflict_globalval": "變量名與系統變量有衝突,請使用其他變量名",
"team_tags_set": "團隊標籤",
"temperature": "溫度",
"temperature_tip": "範圍 0~10。\n值越大,代表模型回答越發散;值越小,代表回答越嚴謹。",
@@ -229,6 +252,8 @@
"upload_file_max_amount_tip": "單輪對話中最大上傳檔案數量",
"variable.select type_desc": "可以為工作流程定義全域變數,常用於暫存。賦值的方式包括:\n1. 從對話頁面的 query 參數取得。\n2. 透過 API 的 variables 物件傳遞。\n3. 透過【變數更新】節點進行賦值。",
"variable.textarea_type_desc": "允許使用者最多輸入 4000 字的對話框。",
+ "variable_name_required": "變量名必填",
+ "variable_repeat": "該變量名已被佔用,無法使用",
"version.Revert success": "復原成功",
"version_back": "回到初始狀態",
"version_copy": "副本",
diff --git a/packages/web/i18n/zh-Hant/common.json b/packages/web/i18n/zh-Hant/common.json
index 59b19134e..9b04babf9 100644
--- a/packages/web/i18n/zh-Hant/common.json
+++ b/packages/web/i18n/zh-Hant/common.json
@@ -114,6 +114,8 @@
"can_copy_content_tip": "無法使用瀏覽器自動複製,請手動複製下面內容",
"chart_mode_cumulative": "累積",
"chart_mode_incremental": "分時",
+ "chat": "會話",
+ "chat_chatId": "會話Id: {{chatId}}",
"choosable": "可選擇",
"chose_condition": "選擇條件",
"chosen": "已選擇",
@@ -679,7 +681,6 @@
"core.module.variable.add option": "新增選項",
"core.module.variable.input type": "文字",
"core.module.variable.key": "變數鍵值",
- "core.module.variable.key already exists": "鍵值已存在",
"core.module.variable.key is required": "變數鍵值為必填",
"core.module.variable.select type": "下拉單選",
"core.module.variable.text max length": "最大長度",
@@ -878,6 +879,7 @@
"max_quote_tokens": "引用上限",
"max_quote_tokens_tips": "單次搜尋最大的 token 數量,中文約 1 字=1.7 tokens,英文約 1 字=1 token",
"mcp_server": "MCP 服務",
+ "member": "成員",
"min_similarity": "最低相關度",
"min_similarity_tip": "不同索引模型的相關度有區別,請透過搜尋測試來選擇合適的數值。\n使用 結果重排 時,使用重排結果過濾。",
"model.billing": "模型計費",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1c3a79a84..c14ca202d 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -121,8 +121,8 @@ importers:
packages/service:
dependencies:
'@fastgpt-sdk/plugin':
- specifier: ^0.1.2
- version: 0.1.2(@types/node@20.17.24)
+ specifier: ^0.1.4
+ version: 0.1.4(@types/node@20.17.24)
'@fastgpt/global':
specifier: workspace:*
version: link:../global
@@ -1973,8 +1973,8 @@ packages:
resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- '@fastgpt-sdk/plugin@0.1.2':
- resolution: {integrity: sha512-z8C0TCCSFxJpF81+V654Xv6SVnLn+/yBNQW78EfZmHe3udZ/WZGmXUTACMac0YrdcT0Wi3TV2/+mmXfePA2CSw==}
+ '@fastgpt-sdk/plugin@0.1.4':
+ resolution: {integrity: sha512-/wDpUvof6f2Elher295D+Z7YDLKY8+PuMORmA7RT+IfQ1sq6OgmTFDYrACrsqxq3Y5mgU8bt4zd5og2U+SmgDQ==}
'@fastify/accept-negotiator@1.1.0':
resolution: {integrity: sha512-OIHZrb2ImZ7XG85HXOONLcJWGosv7sIvM2ifAPQVhg9Lv7qdmMBNVaai4QTdyuaqbKM5eO6sLSQOYI7wEQeCJQ==}
@@ -11208,7 +11208,7 @@ snapshots:
'@eslint/js@8.57.1': {}
- '@fastgpt-sdk/plugin@0.1.2(@types/node@20.17.24)':
+ '@fastgpt-sdk/plugin@0.1.4(@types/node@20.17.24)':
dependencies:
'@fortaine/fetch-event-source': 3.0.6
'@ts-rest/core': 3.52.1(@types/node@20.17.24)(zod@3.25.51)
@@ -15098,7 +15098,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0)(eslint@8.56.0):
+ eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0(eslint-plugin-import@2.31.0)(eslint@8.56.0))(eslint@8.56.0):
dependencies:
debug: 3.2.7
optionalDependencies:
@@ -15109,7 +15109,7 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0)(eslint@8.57.1):
+ eslint-module-utils@2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1):
dependencies:
debug: 3.2.7
optionalDependencies:
@@ -15131,7 +15131,7 @@ snapshots:
doctrine: 2.1.0
eslint: 8.56.0
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0)(eslint@8.56.0)
+ eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.56.0)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0(eslint-plugin-import@2.31.0)(eslint@8.56.0))(eslint@8.56.0)
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
@@ -15160,7 +15160,7 @@ snapshots:
doctrine: 2.1.0
eslint: 8.57.1
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0)(eslint@8.57.1)
+ eslint-module-utils: 2.12.0(@typescript-eslint/parser@6.21.0(eslint@8.57.1)(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.9.0(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1)
hasown: 2.0.2
is-core-module: 2.16.1
is-glob: 4.0.3
diff --git a/projects/app/package.json b/projects/app/package.json
index f347528ff..5aa349d46 100644
--- a/projects/app/package.json
+++ b/projects/app/package.json
@@ -1,6 +1,6 @@
{
"name": "app",
- "version": "4.11.0",
+ "version": "4.11.1",
"private": false,
"scripts": {
"dev": "next dev",
diff --git a/projects/app/src/components/core/app/VariableEdit.tsx b/projects/app/src/components/core/app/VariableEdit.tsx
index 7cdeeacf6..63156eedb 100644
--- a/projects/app/src/components/core/app/VariableEdit.tsx
+++ b/projects/app/src/components/core/app/VariableEdit.tsx
@@ -35,10 +35,10 @@ import DndDrag, {
type DraggableProvided,
type DraggableStateSnapshot
} from '@fastgpt/web/components/common/DndDrag';
+import { workflowSystemVariables } from '@/web/core/app/utils';
import { getNanoid } from '@fastgpt/global/common/string/tools';
export const defaultVariable: VariableItemType = {
- id: getNanoid(6),
key: '',
label: '',
type: VariableInputEnum.input,
@@ -47,12 +47,8 @@ export const defaultVariable: VariableItemType = {
valueType: WorkflowIOValueTypeEnum.string
};
-type InputItemType = VariableItemType & {
- list: { label: string; value: string }[];
-};
-
export const addVariable = () => {
- const newVariable = { ...defaultVariable, key: '', id: '', list: [{ value: '', label: '' }] };
+ const newVariable = { ...defaultVariable, list: [{ value: '', label: '' }] };
return newVariable;
};
@@ -103,23 +99,47 @@ const VariableEdit = ({
});
}, [variables]);
+ /*
+ - New var: random key
+ - Update var: keep key
+ */
const onSubmitSuccess = useCallback(
- (data: InputItemType, action: 'confirm' | 'continue') => {
+ (data: VariableItemType, action: 'confirm' | 'continue') => {
data.label = data?.label?.trim();
+ if (!data.label) {
+ return toast({
+ status: 'warning',
+ title: t('app:variable_name_required')
+ });
+ }
- const existingVariable = variables.find(
- (item) => item.label === data.label && item.id !== data.id
- );
+ // check if the variable already exists
+ const existingVariable = variables.find((item) => {
+ return item.key !== data.key && (data.label === item.label || data.label === item.key);
+ });
if (existingVariable) {
+ return toast({
+ status: 'warning',
+ title: t('app:variable_repeat')
+ });
+ }
+
+ // check if the variable is a system variable
+ if (
+ workflowSystemVariables.some(
+ (item) => item.key === data.label || t(item.label) === data.label
+ )
+ ) {
toast({
status: 'warning',
- title: t('common:core.module.variable.key already exists')
+ title: t('app:systemval_conflict_globalval')
});
return;
}
- data.key = data.label;
- data.enums = data.list;
+ if (data.type !== VariableInputEnum.select && data.list) {
+ delete data.list;
+ }
if (data.type === VariableInputEnum.custom) {
data.required = false;
@@ -127,16 +147,24 @@ const VariableEdit = ({
data.valueType = inputTypeList.find((item) => item.value === data.type)?.defaultValueType;
}
- const onChangeVariable = [...variables];
- if (data.id) {
- const index = variables.findIndex((item) => item.id === data.id);
- onChangeVariable[index] = data;
- } else {
- onChangeVariable.push({
- ...data,
- id: getNanoid(6)
- });
- }
+ const onChangeVariable = (() => {
+ if (data.key) {
+ return variables.map((item) => {
+ if (item.key === data.key) {
+ return data;
+ }
+ return item;
+ });
+ }
+
+ return [
+ ...variables,
+ {
+ ...data,
+ key: getNanoid(8)
+ }
+ ];
+ })();
if (action === 'confirm') {
onChange(onChangeVariable);
@@ -226,7 +254,7 @@ const VariableEdit = ({
{({ provided }) => (
{formatVariables.map((item, index) => (
-
+
{(provided, snapshot) => (
)}
@@ -370,7 +398,7 @@ const TableItem = ({
- {item.key}
+ {item.label}
|
@@ -385,7 +413,10 @@ const TableItem = ({
onClick={() => {
const formattedItem = {
...item,
- list: item.enums?.map((item) => ({ label: item.value, value: item.value })) || []
+ list:
+ item.list ||
+ item.enums?.map((item) => ({ label: item.value, value: item.value })) ||
+ []
};
reset(formattedItem);
}}
@@ -393,7 +424,7 @@ const TableItem = ({
onChange(variables.filter((variable) => variable.id !== item.id))}
+ onClick={() => onChange(variables.filter((variable) => variable.key !== item.key))}
/>
|
diff --git a/projects/app/src/components/core/app/formRender/LabelAndForm.tsx b/projects/app/src/components/core/app/formRender/LabelAndForm.tsx
index 5b466b64d..1f3c45fac 100644
--- a/projects/app/src/components/core/app/formRender/LabelAndForm.tsx
+++ b/projects/app/src/components/core/app/formRender/LabelAndForm.tsx
@@ -34,13 +34,15 @@ const LabelAndFormRender = ({
placeholder,
inputType,
variablesForm,
+ showValueType,
...props
}: {
formKey: string;
- label: string;
+ label: string | React.ReactNode;
required?: boolean;
placeholder?: string;
variablesForm: UseFormReturn;
+ showValueType?: boolean;
} & SpecificProps &
BoxProps) => {
const { control } = variablesForm;
@@ -48,7 +50,7 @@ const LabelAndFormRender = ({
return (
- {label}
+ {typeof label === 'string' ? {label} : label}
{placeholder && }
diff --git a/projects/app/src/components/core/app/formRender/index.tsx b/projects/app/src/components/core/app/formRender/index.tsx
index 00a2dc126..da78160e4 100644
--- a/projects/app/src/components/core/app/formRender/index.tsx
+++ b/projects/app/src/components/core/app/formRender/index.tsx
@@ -11,7 +11,7 @@ import MultipleSelect, {
import JSONEditor from '@fastgpt/web/components/common/Textarea/JsonEditor';
import AIModelSelector from '../../../Select/AIModelSelector';
import FileSelector from '../../../Select/FileSelector';
-import { useTranslation } from '@fastgpt/web/hooks/useSafeTranslation';
+import { useSafeTranslation } from '@fastgpt/web/hooks/useSafeTranslation';
const InputRender = (props: InputRenderProps) => {
const {
@@ -28,7 +28,7 @@ const InputRender = (props: InputRenderProps) => {
return <>{customRender(props)}>;
}
- const { t } = useTranslation();
+ const { t } = useSafeTranslation();
const {
value: selectedValue,
setValue,
@@ -81,6 +81,7 @@ const InputRender = (props: InputRenderProps) => {
return (
) => {
+ e.stopPropagation();
if (e.key.toLowerCase() !== 'enter') return;
handleSubmit(onSubmit, onError)();
};
diff --git a/projects/app/src/global/core/api/appReq.d.ts b/projects/app/src/global/core/api/appReq.d.ts
index 7eec8793c..699030c51 100644
--- a/projects/app/src/global/core/api/appReq.d.ts
+++ b/projects/app/src/global/core/api/appReq.d.ts
@@ -7,7 +7,8 @@ export type GetAppChatLogsProps = {
dateStart: Date;
dateEnd: Date;
sources?: ChatSourceEnum[];
- logTitle?: string;
+ tmbIds?: string[];
+ chatSearch?: string;
};
export type GetAppChatLogsParams = PaginationProps;
diff --git a/projects/app/src/pageComponents/account/model/Log/index.tsx b/projects/app/src/pageComponents/account/model/Log/index.tsx
index 717d335cc..fe72b63dd 100644
--- a/projects/app/src/pageComponents/account/model/Log/index.tsx
+++ b/projects/app/src/pageComponents/account/model/Log/index.tsx
@@ -185,7 +185,6 @@ const ChannelLog = ({ Tab }: { Tab: React.ReactNode }) => {
setFilterProps({ ...filterProps, dateRange: e })}
/>
diff --git a/projects/app/src/pageComponents/account/model/ModelDashboard/index.tsx b/projects/app/src/pageComponents/account/model/ModelDashboard/index.tsx
index f5080edf7..51e5ed504 100644
--- a/projects/app/src/pageComponents/account/model/ModelDashboard/index.tsx
+++ b/projects/app/src/pageComponents/account/model/ModelDashboard/index.tsx
@@ -374,7 +374,6 @@ const ModelDashboard = ({ Tab }: { Tab: React.ReactNode }) => {
diff --git a/projects/app/src/pageComponents/account/usage/UsageDetail.tsx b/projects/app/src/pageComponents/account/usage/UsageDetail.tsx
index b3fe4c8d9..ca9b28780 100644
--- a/projects/app/src/pageComponents/account/usage/UsageDetail.tsx
+++ b/projects/app/src/pageComponents/account/usage/UsageDetail.tsx
@@ -15,12 +15,12 @@ import { type UsageItemType } from '@fastgpt/global/support/wallet/usage/type.d'
import dayjs from 'dayjs';
import { UsageSourceMap } from '@fastgpt/global/support/wallet/usage/constants';
import MyModal from '@fastgpt/web/components/common/MyModal';
-import { useTranslation } from 'next-i18next';
import { formatNumber } from '@fastgpt/global/common/math/tools';
import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
+import { useSafeTranslation } from '@fastgpt/web/hooks/useSafeTranslation';
const UsageDetail = ({ usage, onClose }: { usage: UsageItemType; onClose: () => void }) => {
- const { t } = useTranslation();
+ const { t } = useSafeTranslation();
const filterBillList = useMemo(
() => usage.list.filter((item) => item && item.moduleName),
[usage.list]
diff --git a/projects/app/src/pageComponents/account/usage/UsageTable.tsx b/projects/app/src/pageComponents/account/usage/UsageTable.tsx
index 1c9f658b4..355a01a5d 100644
--- a/projects/app/src/pageComponents/account/usage/UsageTable.tsx
+++ b/projects/app/src/pageComponents/account/usage/UsageTable.tsx
@@ -27,6 +27,7 @@ import { type UsageFilterParams } from './type';
import PopoverConfirm from '@fastgpt/web/components/common/MyPopover/PopoverConfirm';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { downloadFetch } from '@/web/common/system/utils';
+import { useSafeTranslation } from '@fastgpt/web/hooks/useSafeTranslation';
const UsageDetail = dynamic(() => import('./UsageDetail'));
@@ -39,7 +40,7 @@ const UsageTableList = ({
Selectors: React.ReactNode;
filterParams: UsageFilterParams;
}) => {
- const { t } = useTranslation();
+ const { t } = useSafeTranslation();
const { dateRange, selectTmbIds, isSelectAllTmb, usageSources, isSelectAllSource, projectName } =
filterParams;
@@ -147,7 +148,9 @@ const UsageTableList = ({
{t(UsageSourceMap[item.source]?.label as any) || '-'} |
- {t(item.appName as any) || '-'} |
+
+ {t(item.appName as any) || '-'}
+ |
{formatNumber(item.totalPoints) || 0} |
+ }
+ >
+ {({ onClose }) => {
+ return (
+
+
+ onDragEndCb={setLogKeysList}
+ dataList={logKeysList}
+ renderClone={(provided, snapshot, rubric) => (
+
+ )}
+ >
+ {({ provided }) => (
+
+ {logKeysList.map((item, index) => (
+
+ {(provided, snapshot) => (
+ <>
+
+ {index !== logKeysList.length - 1 && }
+ >
+ )}
+
+ ))}
+
+ )}
+
+
+ );
+ }}
+
+ );
+};
+
+export default LogKeysConfigPopover;
+
+const DragItem = ({
+ item,
+ provided,
+ snapshot,
+ logKeys,
+ setLogKeys
+}: {
+ item: AppLogKeysType;
+ provided: DraggableProvided;
+ snapshot: DraggableStateSnapshot;
+ logKeys: AppLogKeysType[];
+ setLogKeys: (logKeys: AppLogKeysType[]) => void;
+}) => {
+ const { t } = useTranslation();
+
+ return (
+
+
+
+
+
+ {t(AppLogKeysEnumMap[item.key])}
+
+
+ {item.enable ? (
+ {
+ setLogKeys(
+ logKeys.map((key) => (key.key === item.key ? { ...key, enable: false } : key))
+ );
+ }}
+ />
+ ) : (
+ {
+ setLogKeys(
+ logKeys.map((key) => (key.key === item.key ? { ...key, enable: true } : key))
+ );
+ }}
+ />
+ )}
+
+ );
+};
diff --git a/projects/app/src/pageComponents/app/detail/Logs/SyncLogKeysPopover.tsx b/projects/app/src/pageComponents/app/detail/Logs/SyncLogKeysPopover.tsx
new file mode 100644
index 000000000..7a9d8379c
--- /dev/null
+++ b/projects/app/src/pageComponents/app/detail/Logs/SyncLogKeysPopover.tsx
@@ -0,0 +1,88 @@
+import MyPopover from '@fastgpt/web/components/common/MyPopover';
+import { Box, Button, Flex } from '@chakra-ui/react';
+import MyIcon from '@fastgpt/web/components/common/Icon';
+import { useTranslation } from 'next-i18next';
+import React from 'react';
+import type { updateLogKeysBody } from '@/pages/api/core/app/logs/updateLogKeys';
+import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
+import { updateLogKeys } from '@/web/core/app/api/log';
+import { useContextSelector } from 'use-context-selector';
+import { AppContext } from '../context';
+import type { AppLogKeysType } from '@fastgpt/global/core/app/logs/type';
+
+const SyncLogKeysPopover = ({
+ logKeys,
+ setLogKeys,
+ teamLogKeys,
+ fetchLogKeys
+}: {
+ logKeys: AppLogKeysType[];
+ setLogKeys: (logKeys: AppLogKeysType[]) => void;
+ teamLogKeys: AppLogKeysType[];
+ fetchLogKeys: () => Promise;
+}) => {
+ const { t } = useTranslation();
+ const appId = useContextSelector(AppContext, (v) => v.appId);
+
+ const { runAsync: updateList, loading: updateLoading } = useRequest2(
+ async (data: updateLogKeysBody) => {
+ await updateLogKeys(data);
+ },
+ {
+ manual: true,
+ onSuccess: async () => {
+ await fetchLogKeys();
+ }
+ }
+ );
+
+ return (
+
+
+
+ }
+ >
+ {({ onClose }) => {
+ return (
+
+ {t('app:sync_log_keys_popover_text')}
+
+
+
+
+
+
+ );
+ }}
+
+ );
+};
+
+export default SyncLogKeysPopover;
diff --git a/projects/app/src/pageComponents/app/detail/Logs/index.tsx b/projects/app/src/pageComponents/app/detail/Logs/index.tsx
index c68f3cbce..34c55c14c 100644
--- a/projects/app/src/pageComponents/app/detail/Logs/index.tsx
+++ b/projects/app/src/pageComponents/app/detail/Logs/index.tsx
@@ -1,4 +1,4 @@
-import React, { useEffect, useMemo, useState } from 'react';
+import React, { useMemo, useState } from 'react';
import {
Flex,
Box,
@@ -10,12 +10,13 @@ import {
Td,
Tbody,
HStack,
- Button
+ Button,
+ Input
} from '@chakra-ui/react';
import UserBox from '@fastgpt/web/components/common/UserBox';
import MyIcon from '@fastgpt/web/components/common/Icon';
import { useTranslation } from 'next-i18next';
-import { getAppChatLogs } from '@/web/core/app/api';
+import { getAppChatLogs } from '@/web/core/app/api/log';
import dayjs from 'dayjs';
import { ChatSourceEnum, ChatSourceMap } from '@fastgpt/global/core/chat/constants';
import { addDays } from 'date-fns';
@@ -27,16 +28,26 @@ import EmptyTip from '@fastgpt/web/components/common/EmptyTip';
import { useContextSelector } from 'use-context-selector';
import { AppContext } from '../context';
import { cardStyles } from '../constants';
-
import dynamic from 'next/dynamic';
import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
import MultipleSelect, {
useMultipleSelect
} from '@fastgpt/web/components/common/MySelect/MultipleSelect';
-import SearchInput from '@fastgpt/web/components/common/Input/SearchInput';
import PopoverConfirm from '@fastgpt/web/components/common/MyPopover/PopoverConfirm';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
import { downloadFetch } from '@/web/common/system/utils';
+import LogKeysConfigPopover from './LogKeysConfigPopover';
+import { getLogKeys } from '@/web/core/app/api/log';
+import { AppLogKeysEnum } from '@fastgpt/global/core/app/logs/constants';
+import { DefaultAppLogKeys } from '@fastgpt/global/core/app/logs/constants';
+import { useScrollPagination } from '@fastgpt/web/hooks/useScrollPagination';
+import { getTeamMembers } from '@/web/support/user/team/api';
+import Avatar from '@fastgpt/web/components/common/Avatar';
+import { useLocalStorageState } from 'ahooks';
+import type { AppLogKeysType } from '@fastgpt/global/core/app/logs/type';
+import type { AppLogsListItemType } from '@/types/app';
+import SyncLogKeysPopover from './SyncLogKeysPopover';
+import { isEqual } from 'lodash';
const DetailLogsModal = dynamic(() => import('./DetailLogsModal'));
@@ -51,7 +62,105 @@ const Logs = () => {
});
const [detailLogsId, setDetailLogsId] = useState();
- const [logTitle, setLogTitle] = useState();
+ const [tmbInputValue, setTmbInputValue] = useState('');
+ const [chatSearch, setChatSearch] = useState('');
+
+ const getCellRenderMap = (item: AppLogsListItemType) => ({
+ [AppLogKeysEnum.SOURCE]: (
+
+ {/* @ts-ignore */}
+ {item.sourceName || t(ChatSourceMap[item.source]?.name) || item.source}
+ |
+ ),
+ [AppLogKeysEnum.CREATED_TIME]: (
+ {dayjs(item.createTime).format('YYYY/MM/DD HH:mm')} |
+ ),
+ [AppLogKeysEnum.LAST_CONVERSATION_TIME]: (
+
+ {dayjs(item.updateTime).format('YYYY/MM/DD HH:mm')}
+ |
+ ),
+ [AppLogKeysEnum.USER]: (
+
+
+ {!!item.outLinkUid ? item.outLinkUid : }
+
+ |
+ ),
+ [AppLogKeysEnum.TITLE]: (
+
+ {item.customTitle || item.title}
+ |
+ ),
+ [AppLogKeysEnum.SESSION_ID]: (
+
+ {item.id || '-'}
+ |
+ ),
+ [AppLogKeysEnum.MESSAGE_COUNT]: {item.messageCount} | ,
+ [AppLogKeysEnum.FEEDBACK]: (
+
+ {!!item?.userGoodFeedbackCount && (
+
+
+ {item.userGoodFeedbackCount}
+
+ )}
+ {!!item?.userBadFeedbackCount && (
+
+
+ {item.userBadFeedbackCount}
+
+ )}
+ {!item?.userGoodFeedbackCount && !item?.userBadFeedbackCount && <>->}
+ |
+ ),
+ [AppLogKeysEnum.CUSTOM_FEEDBACK]: (
+ {item.customFeedbacksCount || '-'} |
+ ),
+ [AppLogKeysEnum.ANNOTATED_COUNT]: (
+ {item.markCount} |
+ ),
+ [AppLogKeysEnum.RESPONSE_TIME]: (
+
+ {item.averageResponseTime ? `${item.averageResponseTime.toFixed(2)}s` : '-'}
+ |
+ ),
+ [AppLogKeysEnum.ERROR_COUNT]: (
+ {item.errorCount || '-'} |
+ ),
+ [AppLogKeysEnum.POINTS]: (
+
+ {item.totalPoints ? `${item.totalPoints.toFixed(2)}` : '-'}
+ |
+ )
+ });
+
+ const {
+ value: selectTmbIds,
+ setValue: setSelectTmbIds,
+ isSelectAll: isSelectAllTmb,
+ setIsSelectAll: setIsSelectAllTmb
+ } = useMultipleSelect([], true);
const {
value: chatSources,
@@ -75,9 +184,19 @@ const Logs = () => {
dateStart: dateRange.from!,
dateEnd: dateRange.to!,
sources: isSelectAllSource ? undefined : chatSources,
- logTitle
+ tmbIds: isSelectAllTmb ? undefined : selectTmbIds,
+ chatSearch
}),
- [appId, chatSources, dateRange.from, dateRange.to, isSelectAllSource, logTitle]
+ [
+ appId,
+ chatSources,
+ dateRange.from,
+ dateRange.to,
+ isSelectAllSource,
+ selectTmbIds,
+ isSelectAllTmb,
+ chatSearch
+ ]
);
const {
data: logs,
@@ -92,6 +211,66 @@ const Logs = () => {
refreshDeps: [params]
});
+ const [logKeys = DefaultAppLogKeys, setLogKeys] = useLocalStorageState(
+ `app_log_keys_${appId}`
+ );
+ const { runAsync: fetchLogKeys, data: teamLogKeys = [] } = useRequest2(
+ async () => {
+ const res = await getLogKeys({ appId });
+ const keys = res.logKeys.length > 0 ? res.logKeys : DefaultAppLogKeys;
+ setLogKeys(keys);
+ return keys;
+ },
+ {
+ manual: false,
+ refreshDeps: [appId]
+ }
+ );
+
+ const HeaderRenderMap = useMemo(
+ () => ({
+ [AppLogKeysEnum.SOURCE]: {t('app:logs_keys_source')} | ,
+ [AppLogKeysEnum.CREATED_TIME]: (
+ {t('app:logs_keys_createdTime')} |
+ ),
+ [AppLogKeysEnum.LAST_CONVERSATION_TIME]: (
+
+ {t('app:logs_keys_lastConversationTime')}
+ |
+ ),
+ [AppLogKeysEnum.USER]: {t('app:logs_chat_user')} | ,
+ [AppLogKeysEnum.TITLE]: {t('app:logs_title')} | ,
+ [AppLogKeysEnum.SESSION_ID]: (
+ {t('app:logs_keys_sessionId')} |
+ ),
+ [AppLogKeysEnum.MESSAGE_COUNT]: (
+ {t('app:logs_message_total')} |
+ ),
+ [AppLogKeysEnum.FEEDBACK]: {t('app:feedback_count')} | ,
+ [AppLogKeysEnum.CUSTOM_FEEDBACK]: (
+
+ {t('common:core.app.feedback.Custom feedback')}
+ |
+ ),
+ [AppLogKeysEnum.ANNOTATED_COUNT]: (
+
+
+ {t('app:mark_count')}
+
+
+ |
+ ),
+ [AppLogKeysEnum.RESPONSE_TIME]: (
+ {t('app:logs_response_time')} |
+ ),
+ [AppLogKeysEnum.ERROR_COUNT]: (
+ {t('app:logs_error_count')} |
+ ),
+ [AppLogKeysEnum.POINTS]: {t('app:logs_points')} |
+ }),
+ [t]
+ );
+
const { runAsync: exportLogs } = useRequest2(
async () => {
await downloadFetch({
@@ -102,7 +281,8 @@ const Logs = () => {
dateStart: dateRange.from || new Date(),
dateEnd: addDays(dateRange.to || new Date(), 1),
sources: isSelectAllSource ? undefined : chatSources,
- logTitle,
+ tmbIds: isSelectAllTmb ? undefined : selectTmbIds,
+ chatSearch,
title: t('app:logs_export_title'),
sourcesMap: Object.fromEntries(
@@ -117,10 +297,36 @@ const Logs = () => {
});
},
{
- refreshDeps: [chatSources, logTitle]
+ refreshDeps: [chatSources]
}
);
+ const { data: members, ScrollData: TmbScrollData } = useScrollPagination(getTeamMembers, {
+ params: { searchKey: tmbInputValue },
+ refreshDeps: [tmbInputValue]
+ });
+ const tmbList = useMemo(
+ () =>
+ members.map((item) => ({
+ label: (
+
+
+
+ {item.memberName}
+
+
+ ),
+ value: item.tmbId
+ })),
+ [members]
+ );
+
+ const showSyncPopover = useMemo(() => {
+ const teamLogKeysList = teamLogKeys.filter((item) => item.enable);
+ const personalLogKeysList = logKeys.filter((item) => item.enable);
+ return !isEqual(teamLogKeysList, personalLogKeysList);
+ }, [teamLogKeys, logKeys]);
+
return (
{
py={[4, 6]}
flex={'1 0 0'}
>
-
-
-
- {t('app:logs_source')}
-
-
-
- list={sourceList}
- value={chatSources}
- onSelect={setChatSources}
- isSelectAll={isSelectAllSource}
- setIsSelectAll={setIsSelectAllSource}
- itemWrap={false}
- height={'32px'}
- bg={'myGray.50'}
- w={'160px'}
- />
-
+
+
+
+ list={sourceList}
+ value={chatSources}
+ onSelect={setChatSources}
+ isSelectAll={isSelectAllSource}
+ setIsSelectAll={setIsSelectAllSource}
+ h={9}
+ w={'226px'}
+ rounded={'8px'}
+ tagStyle={{
+ px: 1,
+ py: 1,
+ borderRadius: 'sm',
+ bg: 'myGray.100',
+ color: 'myGray.900'
+ }}
+ borderColor={'myGray.200'}
+ formLabel={t('app:logs_source')}
+ />
-
-
- {t('common:user.Time')}
-
+
{
setDateRange(date);
}}
+ bg={'white'}
+ h={9}
+ w={'240px'}
+ rounded={'8px'}
+ borderColor={'myGray.200'}
+ formLabel={t('app:logs_date')}
+ _hover={{
+ borderColor: 'primary.300'
+ }}
/>
-
-
- {t('app:logs_title')}
+
+
+ list={tmbList}
+ value={selectTmbIds}
+ onSelect={(val) => {
+ setSelectTmbIds(val as string[]);
+ }}
+ ScrollData={TmbScrollData}
+ isSelectAll={isSelectAllTmb}
+ setIsSelectAll={setIsSelectAllTmb}
+ h={9}
+ w={'226px'}
+ rounded={'8px'}
+ formLabel={t('common:member')}
+ tagStyle={{
+ px: 1,
+ borderRadius: 'sm',
+ bg: 'myGray.100',
+ w: '76px'
+ }}
+ inputValue={tmbInputValue}
+ setInputValue={setTmbInputValue}
+ />
+
+
+
+ {t('common:chat')}
- setLogTitle(e.target.value)}
+
+ setChatSearch(e.target.value)}
+ fontSize={'sm'}
+ border={'none'}
+ pl={0}
+ _focus={{
+ boxShadow: 'none'
+ }}
+ _placeholder={{
+ fontSize: 'sm'
+ }}
/>
+ {showSyncPopover && (
+
+ )}
+
+
{t('common:Export')}}
showCancel
@@ -186,95 +458,28 @@ const Logs = () => {
- {t('common:core.app.logs.Source And Time')} |
- {t('app:logs_chat_user')} |
- {t('app:logs_title')} |
- {t('app:logs_message_total')} |
- {t('app:feedback_count')} |
- {t('common:core.app.feedback.Custom feedback')} |
-
-
- {t('app:mark_count')}
-
-
- |
+ {(logKeys || DefaultAppLogKeys)
+ .filter((logKey) => logKey.enable)
+ .map((logKey) => HeaderRenderMap[logKey.key])}
- {logs.map((item) => (
- setDetailLogsId(item.id)}
- >
-
- {/* @ts-ignore */}
- {item.sourceName || t(ChatSourceMap[item.source]?.name) || item.source}
- {dayjs(item.time).format('YYYY/MM/DD HH:mm')}
- |
-
-
- {!!item.outLinkUid ? (
- item.outLinkUid
- ) : (
-
- )}
-
- |
-
- {item.customTitle || item.title}
- |
- {item.messageCount} |
-
- {!!item?.userGoodFeedbackCount && (
-
-
- {item.userGoodFeedbackCount}
-
- )}
- {!!item?.userBadFeedbackCount && (
-
-
- {item.userBadFeedbackCount}
-
- )}
- {!item?.userGoodFeedbackCount && !item?.userBadFeedbackCount && <>->}
- |
- {item.customFeedbacksCount || '-'} |
- {item.markCount} |
-
- ))}
+ {logs.map((item) => {
+ const cellRenderMap = getCellRenderMap(item);
+ return (
+ setDetailLogsId(item.id)}
+ >
+ {(logKeys || DefaultAppLogKeys)
+ .filter((logKey) => logKey.enable)
+ .map((logKey) => cellRenderMap[logKey.key])}
+
+ );
+ })}
{logs.length === 0 && !isLoading && }
diff --git a/projects/app/src/pageComponents/app/detail/MCPTools/ChatTest.tsx b/projects/app/src/pageComponents/app/detail/MCPTools/ChatTest.tsx
index 425ecf793..295c32876 100644
--- a/projects/app/src/pageComponents/app/detail/MCPTools/ChatTest.tsx
+++ b/projects/app/src/pageComponents/app/detail/MCPTools/ChatTest.tsx
@@ -4,20 +4,21 @@ import { useContextSelector } from 'use-context-selector';
import { AppContext } from '../context';
import ChatItemContextProvider from '@/web/core/chat/context/chatItemContext';
import ChatRecordContextProvider from '@/web/core/chat/context/chatRecordContext';
-import { Box, Button, Flex } from '@chakra-ui/react';
+import { Box, Button, Flex, HStack } from '@chakra-ui/react';
import { cardStyles } from '../constants';
import { useTranslation } from 'react-i18next';
import { type McpToolConfigType } from '@fastgpt/global/core/app/type';
-import { Controller, useForm } from 'react-hook-form';
+import { useForm } from 'react-hook-form';
import { useRequest2 } from '@fastgpt/web/hooks/useRequest';
import Markdown from '@/components/Markdown';
import { postRunMCPTool } from '@/web/core/app/api/plugin';
import { type StoreSecretValueType } from '@fastgpt/global/common/secret/type';
-import InputRender from '@/components/core/app/formRender';
-import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
-import QuestionTip from '@fastgpt/web/components/common/MyTooltip/QuestionTip';
import { valueTypeToInputType } from '@/components/core/app/formRender/utils';
import { getNodeInputTypeFromSchemaInputType } from '@fastgpt/global/core/app/jsonschema';
+import LabelAndFormRender from '@/components/core/app/formRender/LabelAndForm';
+import FormLabel from '@fastgpt/web/components/common/MyBox/FormLabel';
+import ValueTypeLabel from '../WorkflowComponents/Flow/nodes/render/ValueTypeLabel';
+import { valueTypeFormat } from '@fastgpt/global/core/workflow/runtime/utils';
const ChatTest = ({
currentTool,
@@ -32,7 +33,8 @@ const ChatTest = ({
const [output, setOutput] = useState('');
- const { control, handleSubmit, reset } = useForm();
+ const form = useForm();
+ const { handleSubmit, reset } = form;
useEffect(() => {
reset({});
@@ -42,6 +44,20 @@ const ChatTest = ({
const { runAsync: runTool, loading: isRunning } = useRequest2(
async (data: Record) => {
if (!currentTool) return;
+
+ // Format type
+ Object.entries(currentTool?.inputSchema.properties || {}).forEach(
+ ([paramName, paramInfo]) => {
+ const valueType = getNodeInputTypeFromSchemaInputType({
+ type: paramInfo.type,
+ arrayItems: paramInfo.items
+ });
+ if (data[paramName] !== undefined) {
+ data[paramName] = valueTypeFormat(data[paramName], valueType);
+ }
+ }
+ );
+
return await postRunMCPTool({
params: data,
url,
@@ -89,48 +105,35 @@ const ChatTest = ({
{Object.entries(currentTool?.inputSchema.properties || {}).map(
- ([paramName, paramInfo]) => (
- {
- if (!currentTool?.inputSchema.required?.includes(paramName)) return true;
- return !!value;
- }
- }}
- render={({ field: { onChange, value }, fieldState: { error } }) => {
- const inputType = valueTypeToInputType(
- getNodeInputTypeFromSchemaInputType({ type: paramInfo.type })
- );
+ ([paramName, paramInfo]) => {
+ const inputType = valueTypeToInputType(
+ getNodeInputTypeFromSchemaInputType({ type: paramInfo.type })
+ );
+ const required = currentTool?.inputSchema.required?.includes(paramName);
- return (
-
-
- {currentTool?.inputSchema.required?.includes(paramName) && (
-
- *
-
- )}
-
- {paramName}
-
-
-
-
-
+ {paramName}
+
-
- );
- }}
- />
- )
+
+ }
+ required={required}
+ key={paramName}
+ inputType={inputType}
+ formKey={paramName}
+ variablesForm={form}
+ placeholder={paramInfo.description}
+ />
+ );
+ }
)}
>
diff --git a/projects/app/src/pageComponents/app/detail/MCPTools/index.tsx b/projects/app/src/pageComponents/app/detail/MCPTools/index.tsx
index 4db4ace7a..81fe6709c 100644
--- a/projects/app/src/pageComponents/app/detail/MCPTools/index.tsx
+++ b/projects/app/src/pageComponents/app/detail/MCPTools/index.tsx
@@ -6,7 +6,6 @@ import { useContextSelector } from 'use-context-selector';
import { AppContext } from '../context';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import { type McpToolConfigType } from '@fastgpt/global/core/app/type';
-import { type MCPToolSetData } from '@/pageComponents/dashboard/apps/MCPToolsEditModal';
import { type StoreSecretValueType } from '@fastgpt/global/common/secret/type';
const MCPTools = () => {
@@ -15,13 +14,15 @@ const MCPTools = () => {
const toolSetNode = appDetail.modules.find(
(item) => item.flowNodeType === FlowNodeTypeEnum.toolSet
);
- return toolSetNode?.inputs[0].value as MCPToolSetData;
+ return toolSetNode?.toolConfig?.mcpToolSet ?? toolSetNode?.inputs[0].value;
}, [appDetail.modules]);
const [url, setUrl] = useState(toolSetData?.url || '');
const [toolList, setToolList] = useState(toolSetData?.toolList || []);
- const [headerSecret, setHeaderSecret] = useState(toolSetData?.headerSecret);
- const [currentTool, setCurrentTool] = useState(toolSetData?.toolList[0]);
+ const [headerSecret, setHeaderSecret] = useState(
+ toolSetData?.headerSecret ?? {}
+ );
+ const [currentTool, setCurrentTool] = useState(toolSetData.toolList[0]);
return (
diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/ChatTest.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/ChatTest.tsx
index 9a1bb2067..6b726ae37 100644
--- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/ChatTest.tsx
+++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/ChatTest.tsx
@@ -22,18 +22,21 @@ import { useChatStore } from '@/web/core/chat/context/useChatStore';
import MyBox from '@fastgpt/web/components/common/MyBox';
import ChatQuoteList from '@/pageComponents/chat/ChatQuoteList';
import VariablePopover from '@/components/core/chat/ChatContainer/ChatBox/components/VariablePopover';
+import { useCopyData } from '@fastgpt/web/hooks/useCopyData';
type Props = {
isOpen: boolean;
nodes?: StoreNodeItemType[];
edges?: StoreEdgeItemType[];
onClose: () => void;
+ chatId: string;
};
-const ChatTest = ({ isOpen, nodes = [], edges = [], onClose }: Props) => {
+const ChatTest = ({ isOpen, nodes = [], edges = [], onClose, chatId }: Props) => {
const { t } = useTranslation();
const { appDetail } = useContextSelector(AppContext, (v) => v);
const isPlugin = appDetail.type === AppTypeEnum.plugin;
+ const { copyData } = useCopyData();
const { restartChat, ChatContainer, loading } = useChatTest({
nodes,
@@ -118,7 +121,16 @@ const ChatTest = ({ isOpen, nodes = [], edges = [], onClose }: Props) => {
>
- {t('common:core.chat.Run test')}
+
+ {
+ copyData(chatId);
+ }}
+ >
+ {t('common:core.chat.Run test')}
+
+
{!isVariableVisible && }
@@ -199,7 +211,7 @@ const Render = (Props: Props) => {
showNodeStatus
>
-
+
);
diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/header.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/header.tsx
index aa80d09cf..f686df642 100644
--- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/header.tsx
+++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/header.tsx
@@ -25,7 +25,7 @@ export type NodeTemplateListHeaderProps = {
parentId?: string;
type?: TemplateTypeEnum;
searchVal?: string;
- }) => Promise;
+ }) => Promise;
onUpdateParentId: (parentId: string) => void;
};
diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/list.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/list.tsx
index d23761419..684a5f58a 100644
--- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/list.tsx
+++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/list.tsx
@@ -56,7 +56,6 @@ export type TemplateListProps = {
const NodeTemplateListItem = ({
template,
- templateType,
handleAddNode,
isPopover,
onUpdateParentId
@@ -128,11 +127,6 @@ const NodeTemplateListItem = ({
});
}}
onClick={() => {
- if (template.isFolder && template.flowNodeType !== FlowNodeTypeEnum.toolSet) {
- onUpdateParentId(template.id);
- return;
- }
-
const position =
isPopover && handleParams
? handleParams.addNodePosition
@@ -219,10 +213,6 @@ const NodeTemplateList = ({
template: NodeTemplateListItemType;
position: { x: number; y: number };
}) => {
- if (template.isFolder && template.flowNodeType !== FlowNodeTypeEnum.toolSet) {
- return;
- }
-
try {
const templateNode = await (async () => {
try {
diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/useNodeTemplates.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/useNodeTemplates.tsx
index 50892ba1b..eefe37784 100644
--- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/useNodeTemplates.tsx
+++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/components/NodeTemplates/useNodeTemplates.tsx
@@ -69,7 +69,7 @@ export const useNodeTemplates = () => {
const {
data: teamAndSystemApps,
loading: templatesIsLoading,
- runAsync
+ runAsync: loadNodeTemplates
} = useRequest2(
async ({
parentId = '',
@@ -81,12 +81,13 @@ export const useNodeTemplates = () => {
searchVal?: string;
}) => {
if (type === TemplateTypeEnum.teamPlugin) {
+ // app, workflow-plugin, mcp
return getTeamPlugTemplates({
- parentId,
- searchKey: searchVal
+ parentId
}).then((res) => res.filter((app) => app.id !== appId));
}
if (type === TemplateTypeEnum.systemPlugin) {
+ // systemTool
return getSystemPlugTemplates({
searchKey: searchVal,
parentId
@@ -102,13 +103,6 @@ export const useNodeTemplates = () => {
}
);
- const loadNodeTemplates = useCallback(
- async (params: { parentId?: ParentIdType; type?: TemplateTypeEnum; searchVal?: string }) => {
- await runAsync(params);
- },
- [runAsync]
- );
-
const onUpdateParentId = useCallback(
(parentId: ParentIdType) => {
loadNodeTemplates({
diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useUtils.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useUtils.tsx
index 125cb5966..a983d3112 100644
--- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useUtils.tsx
+++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useUtils.tsx
@@ -20,7 +20,14 @@ export const useWorkflowUtils = () => {
}) => {
const nodeLength = nodeList.filter((node) => {
if (node.flowNodeType === flowNodeType) {
- if (node.flowNodeType === FlowNodeTypeEnum.pluginModule) {
+ if (
+ [
+ FlowNodeTypeEnum.pluginModule,
+ FlowNodeTypeEnum.appModule,
+ FlowNodeTypeEnum.toolSet,
+ FlowNodeTypeEnum.tool
+ ].includes(flowNodeType)
+ ) {
return node.pluginId === pluginId;
} else {
return true;
diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeToolSet.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeToolSet.tsx
index efd263456..86230a3f0 100644
--- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeToolSet.tsx
+++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodeToolSet.tsx
@@ -5,18 +5,17 @@ import NodeCard from './render/NodeCard';
import IOTitle from '../components/IOTitle';
import Container from '../components/Container';
import { useTranslation } from 'react-i18next';
-import { type McpToolConfigType } from '@fastgpt/global/core/app/type';
import { Box, Flex } from '@chakra-ui/react';
const NodeToolSet = ({ data, selected }: NodeProps) => {
const { t } = useTranslation();
- const { inputs } = data;
- const toolList: McpToolConfigType[] = inputs[0]?.value?.toolList;
+ const { toolConfig } = data;
+ const toolList = toolConfig?.mcpToolSet?.toolList ?? toolConfig?.systemToolSet?.toolList ?? [];
return (
-
+
{toolList?.map((tool, index) => (
{
}, [nodeList, nodeId]);
const isAppNode = node && AppNodeFlowNodeTypeMap[node?.flowNodeType];
const showVersion = useMemo(() => {
- // 1. Team app/System commercial plugin
+ // 1. MCP tool set do not have version
+ if (isAppNode && node.toolConfig?.mcpToolSet) return false;
+ // 2. Team app/System commercial plugin
if (isAppNode && node?.pluginId && !node?.pluginData?.error) return true;
- // 2. System tool
- if (isAppNode && node.toolConfig) return true;
+ // 3. System tool
+ if (isAppNode && node?.toolConfig?.systemTool) return true;
return false;
}, [isAppNode, node]);
diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/ValueTypeLabel.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/ValueTypeLabel.tsx
index 4a2b96916..ebe4fe21c 100644
--- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/ValueTypeLabel.tsx
+++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/render/ValueTypeLabel.tsx
@@ -1,4 +1,5 @@
import { FlowValueTypeMap } from '@fastgpt/global/core/workflow/node/constant';
+import type { BoxProps } from '@chakra-ui/react';
import { Box } from '@chakra-ui/react';
import type { WorkflowIOValueTypeEnum } from '@fastgpt/global/core/workflow/constants';
import MyTooltip from '@fastgpt/web/components/common/MyTooltip';
@@ -7,11 +8,12 @@ import { useTranslation } from 'next-i18next';
const ValueTypeLabel = ({
valueType,
- valueDesc
+ valueDesc,
+ ...props
}: {
valueType?: WorkflowIOValueTypeEnum;
valueDesc?: string;
-}) => {
+} & BoxProps) => {
const valueTypeData = valueType ? FlowValueTypeMap[valueType] : undefined;
const { t } = useTranslation();
const label = valueTypeData?.label || '';
@@ -30,6 +32,7 @@ const ValueTypeLabel = ({
display={'flex'}
alignItems={'center'}
fontSize={'11px'}
+ {...props}
>
{t(label as any)}
diff --git a/projects/app/src/pageComponents/app/detail/WorkflowComponents/context/index.tsx b/projects/app/src/pageComponents/app/detail/WorkflowComponents/context/index.tsx
index 5787b9cb8..d99351255 100644
--- a/projects/app/src/pageComponents/app/detail/WorkflowComponents/context/index.tsx
+++ b/projects/app/src/pageComponents/app/detail/WorkflowComponents/context/index.tsx
@@ -59,6 +59,7 @@ import WorkflowStatusContextProvider from './workflowStatusContext';
import { type ChatItemType, type UserChatItemValueItemType } from '@fastgpt/global/core/chat/type';
import { type WorkflowInteractiveResponseType } from '@fastgpt/global/core/workflow/template/system/interactive/type';
import { FlowNodeOutputTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
+import { useChatStore } from '@/web/core/chat/context/useChatStore';
/*
Context
@@ -413,6 +414,8 @@ const WorkflowContextProvider = ({
const { t } = useTranslation();
const { toast } = useToast();
+ const { chatId } = useChatStore();
+
const appDetail = useContextSelector(AppContext, (v) => v.appDetail);
const setAppDetail = useContextSelector(AppContext, (v) => v.setAppDetail);
const appId = appDetail._id;
@@ -1091,7 +1094,7 @@ const WorkflowContextProvider = ({
return (
{children}
-
+
);
};
diff --git a/projects/app/src/pageComponents/app/detail/context.tsx b/projects/app/src/pageComponents/app/detail/context.tsx
index 4bbe40671..272a4c0af 100644
--- a/projects/app/src/pageComponents/app/detail/context.tsx
+++ b/projects/app/src/pageComponents/app/detail/context.tsx
@@ -186,7 +186,11 @@ const AppContextProvider = ({ children }: { children: ReactNode }) => {
return delAppById(appDetail._id);
},
{
- onSuccess() {
+ onSuccess(data) {
+ data.forEach((appId) => {
+ localStorage.removeItem(`app_log_keys_${appId}`);
+ });
+
router.replace(`/dashboard/apps`);
},
successToast: t('common:delete_success'),
diff --git a/projects/app/src/pageComponents/chat/ChatHeader.tsx b/projects/app/src/pageComponents/chat/ChatHeader.tsx
index cd48ccd73..8ac25e39b 100644
--- a/projects/app/src/pageComponents/chat/ChatHeader.tsx
+++ b/projects/app/src/pageComponents/chat/ChatHeader.tsx
@@ -23,6 +23,7 @@ import { getMyApps } from '@/web/core/app/api';
import SelectOneResource from '@/components/common/folder/SelectOneResource';
import { ChatItemContext } from '@/web/core/chat/context/chatItemContext';
import VariablePopover from '@/components/core/chat/ChatContainer/ChatBox/components/VariablePopover';
+import { useCopyData } from '@fastgpt/web/hooks/useCopyData';
const ChatHeader = ({
history,
@@ -59,6 +60,7 @@ const ChatHeader = ({
totalRecordsCount={totalRecordsCount}
title={chatData.title || t('common:core.chat.New Chat')}
chatModels={chatData.app.chatModels}
+ chatId={chatData.chatId || ''}
/>
>
@@ -261,19 +263,33 @@ const MobileHeader = ({
export const PcHeader = ({
title,
chatModels,
- totalRecordsCount
+ totalRecordsCount,
+ chatId
}: {
title: string;
chatModels?: string[];
totalRecordsCount: number;
+ chatId: string;
}) => {
const { t } = useTranslation();
+ const { copyData } = useCopyData();
return (
<>
-
- {title}
-
+
+ {
+ copyData(chatId);
+ }}
+ >
+ {title}
+
+
diff --git a/projects/app/src/pageComponents/dashboard/apps/List.tsx b/projects/app/src/pageComponents/dashboard/apps/List.tsx
index 895d05e59..3cac28d76 100644
--- a/projects/app/src/pageComponents/dashboard/apps/List.tsx
+++ b/projects/app/src/pageComponents/dashboard/apps/List.tsx
@@ -98,7 +98,10 @@ const ListItem = () => {
return delAppById(id);
},
{
- onSuccess() {
+ onSuccess(data) {
+ data.forEach((appId) => {
+ localStorage.removeItem(`app_log_keys_${appId}`);
+ });
loadMyApps();
},
successToast: t('common:delete_success'),
diff --git a/projects/app/src/pageComponents/login/RegisterForm.tsx b/projects/app/src/pageComponents/login/RegisterForm.tsx
index de9ba27af..7aa0c36d4 100644
--- a/projects/app/src/pageComponents/login/RegisterForm.tsx
+++ b/projects/app/src/pageComponents/login/RegisterForm.tsx
@@ -50,7 +50,7 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
});
const username = watch('username');
- const { SendCodeBox } = useSendCode({ type: 'register' });
+ const { SendCodeBox, openCodeAuthModal } = useSendCode({ type: 'register' });
const { runAsync: onclickRegister, loading: requesting } = useRequest2(
async ({ username, password, code }: RegisterType) => {
@@ -122,7 +122,7 @@ const RegisterForm = ({ setPageType, loginSuccess }: Props) => {
{
- if (e.key === 'Enter' && !e.shiftKey && !requesting) {
+ if (!openCodeAuthModal && e.key === 'Enter' && !e.shiftKey && !requesting) {
handleSubmit(onclickRegister, onSubmitErr)();
}
}}
diff --git a/projects/app/src/pageComponents/login/index.tsx b/projects/app/src/pageComponents/login/index.tsx
index a88196a11..96832049e 100644
--- a/projects/app/src/pageComponents/login/index.tsx
+++ b/projects/app/src/pageComponents/login/index.tsx
@@ -242,7 +242,7 @@ export const LoginContainer = ({
/>
)}
-
+
{/* main content area */}
{pageType && DynamicComponent ? DynamicComponent : }
@@ -270,7 +270,7 @@ export const LoginContainer = ({
{t('common:support.user.login.can_not_login')}
)}
-
+
diff --git a/projects/app/src/pages/account/usage/index.tsx b/projects/app/src/pages/account/usage/index.tsx
index ba9800ce1..609f2d70c 100644
--- a/projects/app/src/pages/account/usage/index.tsx
+++ b/projects/app/src/pages/account/usage/index.tsx
@@ -111,12 +111,7 @@ const UsageTable = () => {
{t('common:user.Time')}
-
+
{/* {usageTab === UsageTabEnum.dashboard && (
bg={'myGray.50'}
@@ -146,7 +141,7 @@ const UsageTable = () => {
setSelectTmbIds(val as string[]);
}}
itemWrap={false}
- height={'32px'}
+ h={'32px'}
bg={'myGray.50'}
w={'160px'}
ScrollData={ScrollData}
diff --git a/projects/app/src/pages/api/core/ai/model/delete.ts b/projects/app/src/pages/api/core/ai/model/delete.ts
index 4f0c344db..66c613c56 100644
--- a/projects/app/src/pages/api/core/ai/model/delete.ts
+++ b/projects/app/src/pages/api/core/ai/model/delete.ts
@@ -3,8 +3,7 @@ import { NextAPI } from '@/service/middleware/entry';
import { MongoSystemModel } from '@fastgpt/service/core/ai/config/schema';
import { authSystemAdmin } from '@fastgpt/service/support/permission/user/auth';
import { findModelFromAlldata } from '@fastgpt/service/core/ai/model';
-import { updateFastGPTConfigBuffer } from '@fastgpt/service/common/system/config/controller';
-import { loadSystemModels, updatedReloadSystemModel } from '@fastgpt/service/core/ai/config/utils';
+import { updatedReloadSystemModel } from '@fastgpt/service/core/ai/config/utils';
export type deleteQuery = {
model: string;
diff --git a/projects/app/src/pages/api/core/ai/model/updateDefault.ts b/projects/app/src/pages/api/core/ai/model/updateDefault.ts
index d1e735aeb..74e754216 100644
--- a/projects/app/src/pages/api/core/ai/model/updateDefault.ts
+++ b/projects/app/src/pages/api/core/ai/model/updateDefault.ts
@@ -2,8 +2,7 @@ import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/nex
import { NextAPI } from '@/service/middleware/entry';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { MongoSystemModel } from '@fastgpt/service/core/ai/config/schema';
-import { loadSystemModels, updatedReloadSystemModel } from '@fastgpt/service/core/ai/config/utils';
-import { updateFastGPTConfigBuffer } from '@fastgpt/service/common/system/config/controller';
+import { updatedReloadSystemModel } from '@fastgpt/service/core/ai/config/utils';
import type { ModelTypeEnum } from '@fastgpt/global/core/ai/model';
import { authSystemAdmin } from '@fastgpt/service/support/permission/user/auth';
diff --git a/projects/app/src/pages/api/core/app/del.ts b/projects/app/src/pages/api/core/app/del.ts
index 3d2db7e02..f99ac011b 100644
--- a/projects/app/src/pages/api/core/app/del.ts
+++ b/projects/app/src/pages/api/core/app/del.ts
@@ -8,7 +8,7 @@ import { addAuditLog } from '@fastgpt/service/support/user/audit/util';
import { AuditEventEnum } from '@fastgpt/global/support/user/audit/constants';
import { getI18nAppType } from '@fastgpt/service/support/user/audit/util';
-async function handler(req: NextApiRequest, res: NextApiResponse) {
+async function handler(req: NextApiRequest, res: NextApiResponse) {
const { appId } = req.query as { appId: string };
if (!appId) {
@@ -23,7 +23,7 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
per: OwnerPermissionVal
});
- await onDelOneApp({
+ const deletedAppIds = await onDelOneApp({
teamId,
appId
});
@@ -42,6 +42,8 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
// Tracks
pushTrack.countAppNodes({ teamId, tmbId, uid: userId, appId });
+
+ return deletedAppIds;
}
export default NextAPI(handler);
diff --git a/projects/app/src/pages/api/core/app/detail.ts b/projects/app/src/pages/api/core/app/detail.ts
index f383fab9b..2d56ffc87 100644
--- a/projects/app/src/pages/api/core/app/detail.ts
+++ b/projects/app/src/pages/api/core/app/detail.ts
@@ -4,6 +4,7 @@ import { NextAPI } from '@/service/middleware/entry';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { CommonErrEnum } from '@fastgpt/global/common/error/code/common';
import { rewriteAppWorkflowToDetail } from '@fastgpt/service/core/app/utils';
+import { getLocale } from '@fastgpt/service/common/middle/i18n';
/* 获取应用详情 */
async function handler(req: NextApiRequest, res: NextApiResponse) {
@@ -24,7 +25,8 @@ async function handler(req: NextApiRequest, res: NextApiResponse) {
nodes: app.modules,
teamId,
ownerTmbId: app.tmbId,
- isRoot
+ isRoot,
+ lang: getLocale(req)
});
if (!app.permission.hasWritePer) {
diff --git a/projects/app/src/pages/api/core/app/exportChatLogs.ts b/projects/app/src/pages/api/core/app/exportChatLogs.ts
index 360769ed1..d5ab5b7f8 100644
--- a/projects/app/src/pages/api/core/app/exportChatLogs.ts
+++ b/projects/app/src/pages/api/core/app/exportChatLogs.ts
@@ -37,8 +37,8 @@ async function handler(req: ApiRequestProps, res: NextAp
dateStart = addDays(new Date(), -7),
dateEnd = new Date(),
sources,
- logTitle,
-
+ tmbIds,
+ chatSearch,
title,
sourcesMap
} = req.body;
@@ -80,10 +80,12 @@ async function handler(req: ApiRequestProps, res: NextAp
$lte: new Date(dateEnd)
},
...(sources && { source: { $in: sources } }),
- ...(logTitle && {
+ ...(tmbIds && { tmbId: { $in: tmbIds } }),
+ ...(chatSearch && {
$or: [
- { title: { $regex: new RegExp(`${replaceRegChars(logTitle)}`, 'i') } },
- { customTitle: { $regex: new RegExp(`${replaceRegChars(logTitle)}`, 'i') } }
+ { chatId: { $regex: new RegExp(`${replaceRegChars(chatSearch)}`, 'i') } },
+ { title: { $regex: new RegExp(`${replaceRegChars(chatSearch)}`, 'i') } },
+ { customTitle: { $regex: new RegExp(`${replaceRegChars(chatSearch)}`, 'i') } }
]
})
};
diff --git a/projects/app/src/pages/api/core/app/getChatLogs.ts b/projects/app/src/pages/api/core/app/getChatLogs.ts
index 00396e684..24c75c715 100644
--- a/projects/app/src/pages/api/core/app/getChatLogs.ts
+++ b/projects/app/src/pages/api/core/app/getChatLogs.ts
@@ -12,10 +12,10 @@ import { readFromSecondary } from '@fastgpt/service/common/mongo/utils';
import { parsePaginationRequest } from '@fastgpt/service/common/api/pagination';
import { type PaginationResponse } from '@fastgpt/web/common/fetch/type';
import { addSourceMember } from '@fastgpt/service/support/user/utils';
-import { replaceRegChars } from '@fastgpt/global/common/string/tools';
import { addAuditLog } from '@fastgpt/service/support/user/audit/util';
import { AuditEventEnum } from '@fastgpt/global/support/user/audit/constants';
import { getI18nAppType } from '@fastgpt/service/support/user/audit/util';
+import { replaceRegChars } from '@fastgpt/global/common/string/tools';
async function handler(
req: NextApiRequest,
@@ -26,7 +26,8 @@ async function handler(
dateStart = addDays(new Date(), -7),
dateEnd = new Date(),
sources,
- logTitle
+ tmbIds,
+ chatSearch
} = req.body as GetAppChatLogsParams;
const { pageSize = 20, offset } = parsePaginationRequest(req);
@@ -51,10 +52,12 @@ async function handler(
$lte: new Date(dateEnd)
},
...(sources && { source: { $in: sources } }),
- ...(logTitle && {
+ ...(tmbIds && { tmbId: { $in: tmbIds.map((item) => new Types.ObjectId(item)) } }),
+ ...(chatSearch && {
$or: [
- { title: { $regex: new RegExp(`${replaceRegChars(logTitle)}`, 'i') } },
- { customTitle: { $regex: new RegExp(`${replaceRegChars(logTitle)}`, 'i') } }
+ { chatId: { $regex: new RegExp(`${replaceRegChars(chatSearch)}`, 'i') } },
+ { title: { $regex: new RegExp(`${replaceRegChars(chatSearch)}`, 'i') } },
+ { customTitle: { $regex: new RegExp(`${replaceRegChars(chatSearch)}`, 'i') } }
]
})
};
@@ -123,6 +126,49 @@ async function handler(
0
]
}
+ },
+ totalResponseTime: {
+ $sum: {
+ $cond: [{ $eq: ['$obj', 'AI'] }, { $ifNull: ['$durationSeconds', 0] }, 0]
+ }
+ },
+ aiMessageCount: {
+ $sum: {
+ $cond: [{ $eq: ['$obj', 'AI'] }, 1, 0]
+ }
+ },
+ errorCount: {
+ $sum: {
+ $cond: [
+ {
+ $gt: [
+ {
+ $size: {
+ $filter: {
+ input: { $ifNull: ['$responseData', []] },
+ as: 'item',
+ cond: { $ne: [{ $ifNull: ['$$item.errorText', null] }, null] }
+ }
+ }
+ },
+ 0
+ ]
+ },
+ 1,
+ 0
+ ]
+ }
+ },
+ totalPoints: {
+ $sum: {
+ $reduce: {
+ input: { $ifNull: ['$responseData', []] },
+ initialValue: 0,
+ in: {
+ $add: ['$$value', { $ifNull: ['$$this.totalPoints', 0] }]
+ }
+ }
+ }
}
}
}
@@ -142,7 +188,23 @@ async function handler(
customFeedbacksCount: {
$ifNull: [{ $arrayElemAt: ['$chatItemsData.customFeedback', 0] }, 0]
},
- markCount: { $ifNull: [{ $arrayElemAt: ['$chatItemsData.adminMark', 0] }, 0] }
+ markCount: { $ifNull: [{ $arrayElemAt: ['$chatItemsData.adminMark', 0] }, 0] },
+ averageResponseTime: {
+ $cond: [
+ {
+ $gt: [{ $ifNull: [{ $arrayElemAt: ['$chatItemsData.aiMessageCount', 0] }, 0] }, 0]
+ },
+ {
+ $divide: [
+ { $ifNull: [{ $arrayElemAt: ['$chatItemsData.totalResponseTime', 0] }, 0] },
+ { $ifNull: [{ $arrayElemAt: ['$chatItemsData.aiMessageCount', 0] }, 1] }
+ ]
+ },
+ 0
+ ]
+ },
+ errorCount: { $ifNull: [{ $arrayElemAt: ['$chatItemsData.errorCount', 0] }, 0] },
+ totalPoints: { $ifNull: [{ $arrayElemAt: ['$chatItemsData.totalPoints', 0] }, 0] }
}
},
{
@@ -153,12 +215,16 @@ async function handler(
customTitle: 1,
source: 1,
sourceName: 1,
- time: '$updateTime',
+ updateTime: 1,
+ createTime: 1,
messageCount: 1,
userGoodFeedbackCount: 1,
userBadFeedbackCount: 1,
customFeedbacksCount: 1,
markCount: 1,
+ averageResponseTime: 1,
+ errorCount: 1,
+ totalPoints: 1,
outLinkUid: 1,
tmbId: 1
}
diff --git a/projects/app/src/pages/api/core/app/logs/getLogKeys.ts b/projects/app/src/pages/api/core/app/logs/getLogKeys.ts
new file mode 100644
index 000000000..f516fc27b
--- /dev/null
+++ b/projects/app/src/pages/api/core/app/logs/getLogKeys.ts
@@ -0,0 +1,36 @@
+import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
+import { NextAPI } from '@/service/middleware/entry';
+import { MongoAppLogKeys } from '@fastgpt/service/core/app/logs/logkeysSchema';
+import type { AppLogKeysSchemaType } from '@fastgpt/global/core/app/logs/type';
+import { authApp } from '@fastgpt/service/support/permission/app/auth';
+import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
+
+export type getLogKeysQuery = {
+ appId: string;
+};
+
+export type getLogKeysBody = {};
+
+export type getLogKeysResponse = {
+ logKeys: AppLogKeysSchemaType['logKeys'];
+};
+
+async function handler(
+ req: ApiRequestProps,
+ res: ApiResponseType
+): Promise {
+ const { appId } = req.query;
+
+ const { teamId } = await authApp({
+ req,
+ authToken: true,
+ appId,
+ per: WritePermissionVal
+ });
+
+ const result = await MongoAppLogKeys.findOne({ teamId, appId });
+
+ return { logKeys: result?.logKeys || [] };
+}
+
+export default NextAPI(handler);
diff --git a/projects/app/src/pages/api/core/app/logs/updateLogKeys.ts b/projects/app/src/pages/api/core/app/logs/updateLogKeys.ts
new file mode 100644
index 000000000..da2367990
--- /dev/null
+++ b/projects/app/src/pages/api/core/app/logs/updateLogKeys.ts
@@ -0,0 +1,34 @@
+import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
+import { NextAPI } from '@/service/middleware/entry';
+import { MongoAppLogKeys } from '@fastgpt/service/core/app/logs/logkeysSchema';
+import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
+import { authApp } from '@fastgpt/service/support/permission/app/auth';
+import type { AppLogKeysType } from '@fastgpt/global/core/app/logs/type';
+
+export type updateLogKeysQuery = {};
+
+export type updateLogKeysBody = {
+ appId: string;
+ logKeys: AppLogKeysType[];
+};
+
+export type updateLogKeysResponse = {};
+
+async function handler(
+ req: ApiRequestProps,
+ res: ApiResponseType
+): Promise {
+ const { appId, logKeys } = req.body;
+ const { teamId } = await authApp({
+ req,
+ authToken: true,
+ appId,
+ per: WritePermissionVal
+ });
+
+ await MongoAppLogKeys.findOneAndUpdate({ teamId, appId }, { logKeys }, { upsert: true });
+
+ return {};
+}
+
+export default NextAPI(handler);
diff --git a/projects/app/src/pages/api/core/app/mcpTools/create.ts b/projects/app/src/pages/api/core/app/mcpTools/create.ts
index 7b287f7a4..22d2ed00f 100644
--- a/projects/app/src/pages/api/core/app/mcpTools/create.ts
+++ b/projects/app/src/pages/api/core/app/mcpTools/create.ts
@@ -7,10 +7,7 @@ import { type CreateAppBody, onCreateApp } from '../create';
import { type McpToolConfigType } from '@fastgpt/global/core/app/type';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
-import {
- getMCPToolRuntimeNode,
- getMCPToolSetRuntimeNode
-} from '@fastgpt/global/core/app/mcpTools/utils';
+import { getMCPToolSetRuntimeNode } from '@fastgpt/global/core/app/mcpTools/utils';
import { pushTrack } from '@fastgpt/service/common/middle/tracks/utils';
import { checkTeamAppLimit } from '@fastgpt/service/support/permission/teamLimit';
import { WritePermissionVal } from '@fastgpt/global/support/permission/constant';
@@ -58,32 +55,13 @@ async function handler(
toolList,
name,
avatar,
- headerSecret: formatedHeaderAuth
+ headerSecret: formatedHeaderAuth,
+ toolId: ''
})
],
session
});
- for (const tool of toolList) {
- await onCreateApp({
- name: tool.name,
- avatar,
- parentId: mcpToolsId,
- teamId,
- tmbId,
- type: AppTypeEnum.tool,
- intro: tool.description,
- modules: [
- getMCPToolRuntimeNode({
- tool,
- url,
- headerSecret: formatedHeaderAuth
- })
- ],
- session
- });
- }
-
return mcpToolsId;
});
diff --git a/projects/app/src/pages/api/core/app/mcpTools/getChildren.ts b/projects/app/src/pages/api/core/app/mcpTools/getChildren.ts
new file mode 100644
index 000000000..1e4c152bc
--- /dev/null
+++ b/projects/app/src/pages/api/core/app/mcpTools/getChildren.ts
@@ -0,0 +1,33 @@
+import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
+import { NextAPI } from '@/service/middleware/entry';
+import { MongoApp } from '@fastgpt/service/core/app/schema';
+import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
+import type { McpToolConfigType } from '@fastgpt/global/core/app/type';
+import { UserError } from '@fastgpt/global/common/error/utils';
+import { getMCPChildren } from '@fastgpt/service/core/app/mcp';
+
+export type McpGetChildrenmQuery = {
+ id: string;
+};
+export type McpGetChildrenmBody = {};
+export type McpGetChildrenmResponse = (McpToolConfigType & {
+ id: string;
+ avatar: string;
+})[];
+
+async function handler(
+ req: ApiRequestProps,
+ _res: ApiResponseType
+): Promise {
+ const { id } = req.query;
+
+ const app = await MongoApp.findOne({ _id: id }).lean();
+
+ if (!app) return Promise.reject(new UserError('No Mcp Toolset found'));
+
+ if (app.type !== AppTypeEnum.toolSet)
+ return Promise.reject(new UserError('the parent is not a mcp toolset'));
+
+ return getMCPChildren(app);
+}
+export default NextAPI(handler);
diff --git a/projects/app/src/pages/api/core/app/mcpTools/update.ts b/projects/app/src/pages/api/core/app/mcpTools/update.ts
index 89ecc3068..092c46b32 100644
--- a/projects/app/src/pages/api/core/app/mcpTools/update.ts
+++ b/projects/app/src/pages/api/core/app/mcpTools/update.ts
@@ -1,22 +1,12 @@
import type { ApiRequestProps, ApiResponseType } from '@fastgpt/service/type/next';
import { NextAPI } from '@/service/middleware/entry';
-import { type AppDetailType, type McpToolConfigType } from '@fastgpt/global/core/app/type';
+import { type McpToolConfigType } from '@fastgpt/global/core/app/type';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { ManagePermissionVal } from '@fastgpt/global/support/permission/constant';
-import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
-import { isEqual } from 'lodash';
-import { type ClientSession } from 'mongoose';
import { MongoApp } from '@fastgpt/service/core/app/schema';
-import { onDelOneApp } from '@fastgpt/service/core/app/controller';
-import { onCreateApp } from '../create';
-import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
-import {
- getMCPToolRuntimeNode,
- getMCPToolSetRuntimeNode
-} from '@fastgpt/global/core/app/mcpTools/utils';
-import { type MCPToolSetData } from '@/pageComponents/dashboard/apps/MCPToolsEditModal';
+import { getMCPToolSetRuntimeNode } from '@fastgpt/global/core/app/mcpTools/utils';
import { MongoAppVersion } from '@fastgpt/service/core/app/version/schema';
import { type StoreSecretValueType } from '@fastgpt/global/common/secret/type';
import { storeSecretValue } from '@fastgpt/service/common/secret/utils';
@@ -39,149 +29,40 @@ async function handler(
const { appId, url, toolList, headerSecret } = req.body;
const { app } = await authApp({ req, authToken: true, appId, per: ManagePermissionVal });
- const toolSetNode = app.modules.find((item) => item.flowNodeType === FlowNodeTypeEnum.toolSet);
- const toolSetData = toolSetNode?.inputs[0].value as MCPToolSetData;
-
const formatedHeaderAuth = storeSecretValue(headerSecret);
+ // create tool set node
+ const toolSetRuntimeNode = getMCPToolSetRuntimeNode({
+ url,
+ toolList,
+ headerSecret: formatedHeaderAuth,
+ name: app.name,
+ avatar: app.avatar,
+ toolId: ''
+ });
+
await mongoSessionRun(async (session) => {
- if (
- !isEqual(toolSetData, {
- url,
- toolList
- })
- ) {
- await updateMCPChildrenTool({
- parentApp: app,
- toolSetData: {
- url,
- toolList,
- headerSecret: formatedHeaderAuth
- },
- session
- });
- }
-
- // create tool set node
- const toolSetRuntimeNode = getMCPToolSetRuntimeNode({
- url,
- toolList,
- headerSecret: formatedHeaderAuth,
- name: app.name,
- avatar: app.avatar
- });
-
// update app and app version
- await Promise.all([
- MongoApp.updateOne(
- { _id: appId },
- {
- modules: [toolSetRuntimeNode],
- updateTime: new Date()
- },
- { session }
- ),
-
- MongoAppVersion.updateOne(
- { appId },
- {
- $set: {
- nodes: [toolSetRuntimeNode]
- }
- },
- { session }
- )
- ]);
+ await MongoApp.updateOne(
+ { _id: appId },
+ {
+ modules: [toolSetRuntimeNode],
+ updateTime: new Date()
+ },
+ { session }
+ );
+ await MongoAppVersion.updateOne(
+ { appId },
+ {
+ $set: {
+ nodes: [toolSetRuntimeNode]
+ }
+ },
+ { session }
+ );
});
return {};
}
export default NextAPI(handler);
-
-const updateMCPChildrenTool = async ({
- parentApp,
- toolSetData,
- session
-}: {
- parentApp: AppDetailType;
- toolSetData: {
- url: string;
- toolList: McpToolConfigType[];
- headerSecret: StoreSecretValueType;
- };
- session: ClientSession;
-}) => {
- const { teamId, tmbId } = parentApp;
- const dbTools = await MongoApp.find({
- parentId: parentApp._id,
- teamId
- });
-
- // 删除 DB 里有,新的工具列表里没有的工具
- for await (const tool of dbTools) {
- if (!toolSetData.toolList.find((t) => t.name === tool.name)) {
- await onDelOneApp({
- teamId,
- appId: tool._id,
- session
- });
- }
- }
-
- // 创建 DB 里没有,新的工具列表里有的工具
- for await (const tool of toolSetData.toolList) {
- if (!dbTools.find((t) => t.name === tool.name)) {
- await onCreateApp({
- name: tool.name,
- avatar: parentApp.avatar,
- parentId: parentApp._id,
- teamId,
- tmbId,
- type: AppTypeEnum.tool,
- intro: tool.description,
- modules: [
- getMCPToolRuntimeNode({
- tool,
- url: toolSetData.url,
- headerSecret: toolSetData.headerSecret
- })
- ],
- session
- });
- }
- }
-
- // 更新 DB 里有的工具
- for await (const tool of toolSetData.toolList) {
- const dbTool = dbTools.find((t) => t.name === tool.name);
- if (dbTool) {
- await MongoApp.updateOne(
- { _id: dbTool._id },
- {
- modules: [
- getMCPToolRuntimeNode({
- tool,
- url: toolSetData.url,
- headerSecret: toolSetData.headerSecret
- })
- ]
- },
- { session }
- );
- await MongoAppVersion.updateOne(
- { appId: dbTool._id },
- {
- nodes: [
- getMCPToolRuntimeNode({
- tool,
- url: toolSetData.url,
- headerSecret: toolSetData.headerSecret
- })
- ]
- },
- { session }
- );
- }
- }
-};
diff --git a/projects/app/src/pages/api/core/app/plugin/getPreviewNode.ts b/projects/app/src/pages/api/core/app/plugin/getPreviewNode.ts
index a0cbccbc2..9bb01cab1 100644
--- a/projects/app/src/pages/api/core/app/plugin/getPreviewNode.ts
+++ b/projects/app/src/pages/api/core/app/plugin/getPreviewNode.ts
@@ -3,16 +3,14 @@
*/
import { PluginSourceEnum } from '@fastgpt/global/core/app/plugin/constants';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
-import {
- getChildAppPreviewNode,
- splitCombinePluginId
-} from '@fastgpt/service/core/app/plugin/controller';
+import { getChildAppPreviewNode } from '@fastgpt/service/core/app/plugin/controller';
import { type FlowNodeTemplateType } from '@fastgpt/global/core/workflow/type/node.d';
import { NextAPI } from '@/service/middleware/entry';
import { type ApiRequestProps } from '@fastgpt/service/type/next';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import type { NextApiResponse } from 'next';
import { getLocale } from '@fastgpt/service/common/middle/i18n';
+import { splitCombinePluginId } from '@fastgpt/global/core/app/plugin/utils';
export type GetPreviewNodeQuery = { appId: string; versionId?: string };
@@ -27,8 +25,7 @@ async function handler(
if (source === PluginSourceEnum.personal) {
await authApp({ req, authToken: true, appId: pluginId, per: ReadPermissionVal });
}
-
- return getChildAppPreviewNode({ appId: pluginId, versionId, lang: getLocale(req) });
+ return getChildAppPreviewNode({ appId, versionId, lang: getLocale(req) });
}
export default NextAPI(handler);
diff --git a/projects/app/src/pages/api/core/app/plugin/getSystemPluginTemplates.ts b/projects/app/src/pages/api/core/app/plugin/getSystemPluginTemplates.ts
index 7b72ae76b..5e12dbad5 100644
--- a/projects/app/src/pages/api/core/app/plugin/getSystemPluginTemplates.ts
+++ b/projects/app/src/pages/api/core/app/plugin/getSystemPluginTemplates.ts
@@ -9,7 +9,7 @@ import { getLocale } from '@fastgpt/service/common/middle/i18n';
import { authCert } from '@fastgpt/service/support/permission/auth/common';
import type { NextApiResponse } from 'next';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
-import { getSystemPlugins } from '@fastgpt/service/core/app/plugin/controller';
+import { getSystemTools } from '@fastgpt/service/core/app/plugin/controller';
export type GetSystemPluginTemplatesBody = {
searchKey?: string;
@@ -25,7 +25,7 @@ async function handler(
const formatParentId = parentId || null;
const lang = getLocale(req);
- const plugins = await getSystemPlugins();
+ const plugins = await getSystemTools();
return plugins // Just show the active plugins
.filter((item) => item.isActive)
@@ -33,7 +33,7 @@ async function handler(
...plugin,
parentId: plugin.parentId === undefined ? null : plugin.parentId,
templateType: plugin.templateType ?? FlowNodeTemplateTypeEnum.other,
- flowNodeType: FlowNodeTypeEnum.tool,
+ flowNodeType: plugin.isFolder ? FlowNodeTypeEnum.toolSet : FlowNodeTypeEnum.tool,
name: parseI18nString(plugin.name, lang),
intro: parseI18nString(plugin.intro ?? '', lang)
}))
diff --git a/projects/app/src/pages/api/core/app/plugin/getVersionList.ts b/projects/app/src/pages/api/core/app/plugin/getVersionList.ts
index b774c3a47..2007fefdf 100644
--- a/projects/app/src/pages/api/core/app/plugin/getVersionList.ts
+++ b/projects/app/src/pages/api/core/app/plugin/getVersionList.ts
@@ -6,13 +6,12 @@ import { type ApiRequestProps } from '@fastgpt/service/type/next';
import { authApp } from '@fastgpt/service/support/permission/app/auth';
import { ReadPermissionVal } from '@fastgpt/global/support/permission/constant';
import { parsePaginationRequest } from '@fastgpt/service/common/api/pagination';
-import {
- getSystemPluginByIdAndVersionId,
- splitCombinePluginId
-} from '@fastgpt/service/core/app/plugin/controller';
+import { getSystemPluginByIdAndVersionId } from '@fastgpt/service/core/app/plugin/controller';
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';
+import { splitCombinePluginId } from '@fastgpt/global/core/app/plugin/utils';
+import { getMCPParentId } from '@fastgpt/global/core/app/mcpTools/utils';
export type getToolVersionListProps = PaginationProps<{
pluginId?: string;
@@ -36,6 +35,7 @@ async function handler(
list: []
};
}
+
const { source, pluginId: formatPluginId } = splitCombinePluginId(pluginId);
// System tool plugin
@@ -54,9 +54,10 @@ async function handler(
// Workflow plugin
const appId = await (async () => {
- if (source === PluginSourceEnum.personal) {
+ if (source === PluginSourceEnum.personal || source === PluginSourceEnum.mcp) {
+ const appId = getMCPParentId(formatPluginId);
const { app } = await authApp({
- appId: formatPluginId,
+ appId,
req,
per: ReadPermissionVal,
authToken: true
diff --git a/projects/app/src/pages/api/core/app/plugin/path.ts b/projects/app/src/pages/api/core/app/plugin/path.ts
index b61423bfb..082a8f445 100644
--- a/projects/app/src/pages/api/core/app/plugin/path.ts
+++ b/projects/app/src/pages/api/core/app/plugin/path.ts
@@ -6,7 +6,7 @@ import {
} from '@fastgpt/global/common/parentFolder/type';
import { parseI18nString } from '@fastgpt/global/common/i18n/utils';
import { getLocale } from '@fastgpt/service/common/middle/i18n';
-import { getSystemPlugins } from '@fastgpt/service/core/app/plugin/controller';
+import { getSystemTools } from '@fastgpt/service/core/app/plugin/controller';
export type pathQuery = GetPathProps;
@@ -23,7 +23,7 @@ async function handler(
if (!pluginId) return [];
- const plugins = await getSystemPlugins();
+ const plugins = await getSystemTools();
const plugin = plugins.find((item) => item.id === pluginId);
if (!plugin) return [];
diff --git a/projects/app/src/pages/api/support/mcp/client/getTools.ts b/projects/app/src/pages/api/support/mcp/client/getTools.ts
index 0b2371848..48eeda8fe 100644
--- a/projects/app/src/pages/api/support/mcp/client/getTools.ts
+++ b/projects/app/src/pages/api/support/mcp/client/getTools.ts
@@ -24,7 +24,8 @@ async function handler(
})
});
- return mcpClient.getTools();
+ const result = await mcpClient.getTools();
+ return result;
}
export default NextAPI(handler);
diff --git a/projects/app/src/pages/api/support/mcp/client/runTool.ts b/projects/app/src/pages/api/support/mcp/client/runTool.ts
index 3e4ccb9f4..bb94126ff 100644
--- a/projects/app/src/pages/api/support/mcp/client/runTool.ts
+++ b/projects/app/src/pages/api/support/mcp/client/runTool.ts
@@ -20,7 +20,6 @@ async function handler(
res: ApiResponseType
): Promise {
const { url, toolName, headerSecret, params } = req.body;
-
const mcpClient = new MCPClient({
url,
headers: getSecretValue({
diff --git a/projects/app/src/pages/api/support/user/team/plan/getTeamPlanStatus.ts b/projects/app/src/pages/api/support/user/team/plan/getTeamPlanStatus.ts
index 5004c5bcf..bd0afd446 100644
--- a/projects/app/src/pages/api/support/user/team/plan/getTeamPlanStatus.ts
+++ b/projects/app/src/pages/api/support/user/team/plan/getTeamPlanStatus.ts
@@ -33,7 +33,7 @@ async function handler(
MongoApp.countDocuments({
teamId,
type: {
- $in: [AppTypeEnum.simple, AppTypeEnum.workflow, AppTypeEnum.plugin, AppTypeEnum.tool]
+ $in: [AppTypeEnum.simple, AppTypeEnum.workflow, AppTypeEnum.plugin, AppTypeEnum.toolSet]
}
}),
MongoDataset.countDocuments({
diff --git a/projects/app/src/pages/dashboard/apps/index.tsx b/projects/app/src/pages/dashboard/apps/index.tsx
index dda87dbb8..d58fd2e1e 100644
--- a/projects/app/src/pages/dashboard/apps/index.tsx
+++ b/projects/app/src/pages/dashboard/apps/index.tsx
@@ -95,7 +95,11 @@ const MyApps = ({ MenuIcon }: { MenuIcon: JSX.Element }) => {
errorToast: 'Error'
});
const { runAsync: onDeleFolder } = useRequest2(delAppById, {
- onSuccess() {
+ onSuccess(data) {
+ data.forEach((appId) => {
+ localStorage.removeItem(`app_log_keys_${appId}`);
+ });
+
router.replace({
query: {
parentId: folderDetail?.parentId
diff --git a/projects/app/src/service/common/system/cron.ts b/projects/app/src/service/common/system/cron.ts
index c2c450c29..70127a395 100644
--- a/projects/app/src/service/common/system/cron.ts
+++ b/projects/app/src/service/common/system/cron.ts
@@ -13,6 +13,7 @@ import { addHours } from 'date-fns';
import { getScheduleTriggerApp } from '@/service/core/app/utils';
import { clearExpiredRawTextBufferCron } from '@fastgpt/service/common/buffer/rawText/controller';
import { clearExpiredDatasetImageCron } from '@fastgpt/service/core/dataset/image/controller';
+import { cronRefreshModels } from '@fastgpt/service/core/ai/config/utils';
// Try to run train every minute
const setTrainingQueueCron = () => {
@@ -88,4 +89,5 @@ export const startCron = () => {
scheduleTriggerAppCron();
clearExpiredRawTextBufferCron();
clearExpiredDatasetImageCron();
+ cronRefreshModels();
};
diff --git a/projects/app/src/types/app.d.ts b/projects/app/src/types/app.d.ts
index d24dbcc16..9669c4e29 100644
--- a/projects/app/src/types/app.d.ts
+++ b/projects/app/src/types/app.d.ts
@@ -38,7 +38,8 @@ export type AppLogsListItemType = {
_id: string;
id: string;
source: string;
- time: Date;
+ createTime: Date;
+ updateTime: Date;
title: string;
customTitle: string;
messageCount: number;
@@ -46,6 +47,9 @@ export type AppLogsListItemType = {
userBadFeedbackCount: number;
customFeedbacksCount: number;
markCount: number;
+ averageResponseTime: number;
+ errorCount: number;
+ totalPoints: number;
outLinkUid?: string;
tmbId: string;
sourceMember: SourceMember;
diff --git a/projects/app/src/web/core/app/api.ts b/projects/app/src/web/core/app/api.ts
index fabf8da4d..fa31ec5d2 100644
--- a/projects/app/src/web/core/app/api.ts
+++ b/projects/app/src/web/core/app/api.ts
@@ -1,11 +1,9 @@
import { GET, POST, DELETE, PUT } from '@/web/common/api/request';
import type { AppDetailType, AppListItemType } from '@fastgpt/global/core/app/type.d';
-import type { GetAppChatLogsParams } from '@/global/core/api/appReq.d';
import type { AppUpdateParams, AppChangeOwnerBody } from '@/global/core/app/api';
import type { CreateAppBody } from '@/pages/api/core/app/create';
import type { ListAppBody } from '@/pages/api/core/app/list';
-import type { AppLogsListItemType } from '@/types/app';
-import type { PaginationResponse } from '@fastgpt/web/common/fetch/type';
+
import type { getBasicInfoResponse } from '@/pages/api/core/app/getBasicInfo';
/**
@@ -25,7 +23,7 @@ export const getMyAppsByTags = (data: {}) => POST(`/proApi/core/chat/team/getApp
/**
* 根据 ID 删除应用
*/
-export const delAppById = (id: string) => DELETE(`/core/app/del?appId=${id}`);
+export const delAppById = (id: string) => DELETE(`/core/app/del?appId=${id}`);
/**
* 根据 ID 获取应用
@@ -44,10 +42,6 @@ export const putAppById = (id: string, data: AppUpdateParams) =>
export const getAppBasicInfoByIds = (ids: string[]) =>
POST(`/core/app/getBasicInfo`, { ids });
-// =================== chat logs
-export const getAppChatLogs = (data: GetAppChatLogsParams) =>
- POST>(`/core/app/getChatLogs`, data, { maxQuantity: 1 });
-
export const resumeInheritPer = (appId: string) =>
GET(`/core/app/resumeInheritPermission`, { appId });
diff --git a/projects/app/src/web/core/app/api/log.ts b/projects/app/src/web/core/app/api/log.ts
new file mode 100644
index 000000000..4ab3412f0
--- /dev/null
+++ b/projects/app/src/web/core/app/api/log.ts
@@ -0,0 +1,15 @@
+import type { getLogKeysQuery, getLogKeysResponse } from '@/pages/api/core/app/logs/getLogKeys';
+import type { updateLogKeysBody } from '@/pages/api/core/app/logs/updateLogKeys';
+import { GET, POST } from '@/web/common/api/request';
+import type { AppLogsListItemType } from '@/types/app';
+import type { PaginationResponse } from '@fastgpt/web/common/fetch/type';
+import type { GetAppChatLogsParams } from '@/global/core/api/appReq';
+
+export const updateLogKeys = (data: updateLogKeysBody) =>
+ POST('/core/app/logs/updateLogKeys', data);
+
+export const getLogKeys = (data: getLogKeysQuery) =>
+ GET('/core/app/logs/getLogKeys', data);
+
+export const getAppChatLogs = (data: GetAppChatLogsParams) =>
+ POST>(`/core/app/getChatLogs`, data, { maxQuantity: 1 });
diff --git a/projects/app/src/web/core/app/api/plugin.ts b/projects/app/src/web/core/app/api/plugin.ts
index 5359a65b1..703435017 100644
--- a/projects/app/src/web/core/app/api/plugin.ts
+++ b/projects/app/src/web/core/app/api/plugin.ts
@@ -5,7 +5,7 @@ import type {
FlowNodeTemplateType,
NodeTemplateListItemType
} from '@fastgpt/global/core/workflow/type/node';
-import { getMyApps } from '../api';
+import { getAppDetailById, getMyApps } from '../api';
import type { ListAppBody } from '@/pages/api/core/app/list';
import { FlowNodeTypeEnum } from '@fastgpt/global/core/workflow/node/constant';
import { FlowNodeTemplateTypeEnum } from '@fastgpt/global/core/workflow/constants';
@@ -13,6 +13,7 @@ import type { GetPreviewNodeQuery } from '@/pages/api/core/app/plugin/getPreview
import { AppTypeEnum } from '@fastgpt/global/core/app/constants';
import type {
GetPathProps,
+ ParentIdType,
ParentTreePathItemType
} from '@fastgpt/global/common/parentFolder/type';
import type { GetSystemPluginTemplatesBody } from '@/pages/api/core/app/plugin/getSystemPluginTemplates';
@@ -28,10 +29,26 @@ import type {
getToolVersionListProps,
getToolVersionResponse
} from '@/pages/api/core/app/plugin/getVersionList';
+import type { McpGetChildrenmResponse } from '@/pages/api/core/app/mcpTools/getChildren';
/* ============ team plugin ============== */
-export const getTeamPlugTemplates = (data?: ListAppBody) =>
- getMyApps(data).then((res) =>
+export const getTeamPlugTemplates = async (data?: {
+ parentId?: ParentIdType;
+ searchKey?: string;
+}) => {
+ if (data?.parentId) {
+ // handle get mcptools
+ const app = await getAppDetailById(data.parentId);
+ if (app.type === AppTypeEnum.toolSet) {
+ const children = await getMcpChildren(data.parentId);
+ return children.map((item) => ({
+ ...item,
+ flowNodeType: FlowNodeTypeEnum.tool,
+ templateType: FlowNodeTemplateTypeEnum.teamApp
+ }));
+ }
+ }
+ return getMyApps(data).then((res) =>
res.map((app) => ({
tmbId: app.tmbId,
id: app._id,
@@ -56,6 +73,7 @@ export const getTeamPlugTemplates = (data?: ListAppBody) =>
sourceMember: app.sourceMember
}))
);
+};
/* ============ system plugin ============== */
export const getSystemPlugTemplates = (data: GetSystemPluginTemplatesBody) =>
@@ -91,6 +109,9 @@ export const getMCPTools = (data: getMCPToolsBody) =>
export const postRunMCPTool = (data: RunMCPToolBody) =>
POST('/support/mcp/client/runTool', data, { timeout: 300000 });
+export const getMcpChildren = (id: string) =>
+ GET('/core/app/mcpTools/getChildren', { id });
+
/* ============ http plugin ============== */
export const postCreateHttpPlugin = (data: createHttpPluginBody) =>
POST('/core/app/httpPlugin/create', data);
diff --git a/projects/app/src/web/core/chat/context/chatItemContext.tsx b/projects/app/src/web/core/chat/context/chatItemContext.tsx
index d3b1fae89..2da897362 100644
--- a/projects/app/src/web/core/chat/context/chatItemContext.tsx
+++ b/projects/app/src/web/core/chat/context/chatItemContext.tsx
@@ -19,6 +19,7 @@ type ContextProps = {
showNodeStatus: boolean;
};
type ChatBoxDataType = {
+ chatId?: string;
appId: string;
title?: string;
userAvatar?: string;
diff --git a/projects/app/src/web/core/workflow/utils.ts b/projects/app/src/web/core/workflow/utils.ts
index bdd67c3ab..3a8550939 100644
--- a/projects/app/src/web/core/workflow/utils.ts
+++ b/projects/app/src/web/core/workflow/utils.ts
@@ -181,6 +181,11 @@ export const filterSensitiveNodesData = (nodes: StoreNodeItemType[]) => {
});
}
+ for (const input of node.inputs) {
+ if (input.key === NodeInputKeyEnum.systemInputConfig) {
+ input.value = undefined;
+ }
+ }
return node;
});
return cloneNodes;
diff --git a/projects/app/src/web/support/user/hooks/useSendCode.tsx b/projects/app/src/web/support/user/hooks/useSendCode.tsx
index 6e428df27..1035bf0a8 100644
--- a/projects/app/src/web/support/user/hooks/useSendCode.tsx
+++ b/projects/app/src/web/support/user/hooks/useSendCode.tsx
@@ -105,7 +105,8 @@ export const useSendCode = ({ type }: { type: `${UserAuthTypeEnum}` }) => {
sendCode,
sendCodeText,
codeCountDown,
- SendCodeBox
+ SendCodeBox,
+ openCodeAuthModal
};
};
diff --git a/test/cases/function/packages/global/common/string/textSplitter.test.ts b/test/cases/function/packages/global/common/string/textSplitter.test.ts
index ba01a3041..1f79a70bc 100644
--- a/test/cases/function/packages/global/common/string/textSplitter.test.ts
+++ b/test/cases/function/packages/global/common/string/textSplitter.test.ts
@@ -559,9 +559,8 @@ FastGPT AI 相关参数配置说明
it(`Test splitText2Chunks 9`, () => {
const mock = {
text: `测试的呀,第一个表格
-
| 序号 | 姓名 | 年龄 | 职业 | 城市 |
-|------|------|------|------|------|
+| --- | --- | --- | --- | --- |
| 1 | 张三 | 25 | 工程师 | 北京 |
| 2 | 李四 | 30 | 教师 | 上海 |
| 3 | 王五 | 28 | 医生 | 广州 |
@@ -600,7 +599,7 @@ it(`Test splitText2Chunks 9`, () => {
这是第二段了,第二表格
| 序号 | 姓名 | 年龄 | 职业 | 城市 |
-|------|------|------|------|------|
+| --- | --- | --- | --- | --- |
| 1 | 张三 | 25 | 工程师 | 北京 |
| 6 | 周八 | 32 | 会计 | 成都 |
| 2 | 李四 | 30 | 教师 | 上海 |
@@ -615,11 +614,10 @@ it(`Test splitText2Chunks 9`, () => {
| 10004 | 黄末 | 28 | 作家 | 厦门 |
| 10013 | 杨一 | 34 | 程序员 | 厦门 |
-
结束了
| 序号22 | 姓名 | 年龄 | 职业 | 城市 |
-|------|------|------|------|------|
+| --- | --- | --- | --- | --- |
| 1 | 张三 | 25 | 工程师 | 北京 |
| 2 | 李四 | 30 | 教师 | 上海 |
| 3 | 王五 | 28 | 医生 | 广州 |
@@ -636,7 +634,6 @@ it(`Test splitText2Chunks 9`, () => {
`,
result: [
`测试的呀,第一个表格
-
| 序号 | 姓名 | 年龄 | 职业 | 城市 |
| --- | --- | --- | --- | --- |
| 1 | 张三 | 25 | 工程师 | 北京 |
@@ -655,9 +652,7 @@ it(`Test splitText2Chunks 9`, () => {
| 1001 | 杨一 | 34 | 程序员 | 厦门 |
| 1002 | 杨二 | 34 | 程序员 | 厦门 |
| 1003 | 杨三 | 34 | 程序员 | 厦门 |`,
- `| 序号 | 姓名 | 年龄 | 职业 | 城市 |
-| --- | --- | --- | --- | --- |
-| 6 | 周八 | 32 | 会计 | 成都 |
+ `| 6 | 周八 | 32 | 会计 | 成都 |
| 1004 | 杨四 | 34 | 程序员 | 厦门 |
| 1005 | 杨五 | 34 | 程序员 | 厦门 |
| 1000 | 黄末 | 28 | 作家 | 厦门 |
@@ -670,15 +665,11 @@ it(`Test splitText2Chunks 9`, () => {
| 1002 | 杨二 | 34 | 程序员 | 厦门 |
| 1003 | 杨三 | 34 | 程序员 | 厦门 |
| 1004 | 杨四 | 34 | 程序员 | 厦门 |
-| 1005 | 杨五 | 34 | 程序员 | 厦门 |`,
- `| 序号 | 姓名 | 年龄 | 职业 | 城市 |
-| --- | --- | --- | --- | --- |
+| 1005 | 杨五 | 34 | 程序员 | 厦门 |
| 6 | 周八 | 32 | 会计 | 成都 |
| 1000 | 黄末 | 28 | 作家 | 厦门 |
-| 1000 | 黄末 | 28 | 作家 | 厦门 |
-| 1000 | 黄末 | 28 | 作家 | 厦门 |
-
-这是第二段了,第二表格
+| 1000 | 黄末 | 28 | 作家 | 厦门 |`,
+ `这是第二段了,第二表格
| 序号 | 姓名 | 年龄 | 职业 | 城市 |
| --- | --- | --- | --- | --- |
@@ -807,3 +798,154 @@ af da da fda a a`,
const { chunks } = splitText2Chunks({ text: mock.text, chunkSize: 2000, paragraphChunkDeep: 2 });
expect(chunks).toEqual(mock.result);
});
+
+// 表格合并测试
+it(`Test splitText2Chunks 13 - Table split with empty lastText`, () => {
+ const mock = {
+ text: `
+## 4.1、关键假设及盈利预测
+
+公司医药工业产品线按治疗领域分心血管类、补益类、清热类、妇科类和其他药品,商业分部包含自有产品销售,相应有分部间抵消,我们分别给予营收增速和毛利率假设, 如下:
+
+1)心脑血管类:心脑血管类为公司核心优势产品,产品包括安宫牛黄丸、牛黄清心丸、同仁堂大活络丸等,2021-2023 年心脑血管类产品营收增速逐年下滑, 毛利率受主要原材料牛黄和麝香价格涨幅较大影响,毛利率承压。我们分别假设 2024-2026 年,心脑血管类产品营收增速分别为 0%、8%和 10%,2025 年受消费上升带动开始恢复性增长,毛利率分别为 47%、50%和 52%,毛利率逐年提升,反映牛黄进口试点后,牛黄原料成本压力缓解。
+
+2)补益类:补益类是公司第二大产品线,包括六味地黄丸、五子衍宗丸等。 我们分别假设 2024-2026 年补益类产品营收年增长 8%、10%和 12%,毛利率均保持稳定为 37.5%。
+
+3)妇科类:妇科类产品包括乌鸡白凤丸、坤宝丸等,历年销售比较平稳。我们假设 2024-2026 年妇科类产品年增长 5%,毛利率维持稳定在 42%。
+
+4)清热类:清热类产品与流行性疾病相关,2023 年为流感大年,感冒清热类产品销售相对旺盛,基数较高。我们假设 2024-2026 年清热类产品年增长-15%、8% 和 10%, 2024 年负增长, 反映上 2023 年基数较高和 2024 年流行性疾病小年影响, 毛利率稳定为 35.0%。
+
+5)其他产品:我们假设 2024-2026 年其他中药品种营收年增长 5%、10%和 15%, 毛利率稳定保持 41%。
+
+6)医药商业:医药商业营收增长主要是旗下同仁堂商业零售门店带动, 2023-2024H1 门店新开显著提速,2024 年上半年新开 116 家门店。我们假设 2024-2026 年医药商业年均增长 9%,毛利率保持 31%水平不变。
+
+7)分部抵消:公司医药商业销售自产药品比例逐年提升,2023 年分部抵消 34.6 亿元,占医药工业营收 31.3%左右,我们假设 2024-2026 年,分部间抵消占医药工业营收分别为 33%、34%和 35%,毛利率为 -2%。
+
+
+
+表 4:同仁堂主营业务关键假设及营收拆分
+
+| 同仁堂经营拆分: | 单位 | 2021A | 2022A | 2023A | 2024E | 2025E | 2026E |
+| --- | --- | --- | --- | --- | --- | --- | --- |
+| 合并营业收入 | 亿元 | 146.03 | 153.72 | 178.61 | 187.68 | 203.30 | 222.68 |
+| 同比 | % | 13.86% | 5.27% | 16.19% | 5.08% | 8.33% | 9.53% |
+| 毛利率 | % | 47.62% | 48.80% | 47.29% | 44.53% | 45.50% | 46.46% |
+| | | | | | | | |
+| 分产品 | | | | | | | |
+| 一、医药工业分部 | 亿元 | 88.76 | 98.40 | 110.79 | 113.42 | 123.59 | 138.44 |
+| 同比 | % | 15.99% | 10.86% | 12.59% | 2.38% | 8.96% | 12.02% |
+| 毛利率 | % | 48.13% | 48.95% | 46.96% | 42.50% | 43.63% | 44.32% |
+| 分细分产品: | | | | | | | |
+| 1、母公司生产:心脑血管类(安宫、清心、大活络等) | 亿元 | 36.29 | 40.63 | 43.88 | 43.88 | 47.39 | 52.13 |
+| 同比 | % | 20.80% | 11.97% | 8.00% | 0.00% | 8.00% | 10.00% |
+| 毛利率 | $ \% $ | 59.96% | 61.20% | 57.62% | 47.00% | 50.00% | 52.00% |
+| | | | | | | | |
+| 2、补益类(六味、金匮、五子衍宗) | | 14.56 | 15.67 | 17.30 | 18.68 | 20.55 | 23.02 |
+| 同比 | % | 2.86% | 7.62% | 10.40% | 8.00% | 10.00% | 12.00% |
+| 毛利率 | $ \% $ | 42.45% | 43.00% | 37.39% | 37.50% | 37.50% | 37.50% |
+| | | | | | | | |
+| 3、妇科类(乌鸡白凤丸、坤宝丸) | | 3.80 | 3.48 | 3.77 | 3.96 | 4.15 | 4.36 |
+| 同比 | % | 23.83% | -8.38% | 8.28% | 5.00% | 5.00% | 5.00% |
+| 毛利率 | % | 40.16% | 38.12% | 42.38% | 42.00% | 42.00% | 42.00% |
+| | | | | | | | |
+| 4、清热类(感冒清热颗粒、牛黄解毒) | 亿元 | 5.24 | 5.29 | 6.14 | 5.22 | 5.64 | 6.20 |
+| 同比 | % | 5.19% | 0.86% | 16.07% | -15.00% | 8.00% | 10.00% |
+| 毛利率 | $ \% $ | 36.09% | 34.39% | 34.97% | 35.00% | 35.00% | 35.00% |
+| | | | | | | | |
+| 5、其他中药品种 | 亿元 | 28.87 | 33.33 | 39.70 | 41.69 | 45.85 | 52.73 |
+| 同比 | % | 18.90% | 15.45% | 19.11% | 5.00% | 10.00% | 15.00% |
+| 毛利率 | $ \% $ | 39.36% | 40.25% | 41.65% | 41.00% | 41.00% | 41.00% |
+| | | | | | | | |
+| 二、商业分部(同仁堂商业) | 亿元 | 82.41 | 84.80 | 102.5 | 111.7 | 121.7 | 132.7 |
+| 同比 | % | 12.64% | 2.90% | 20.83% | 9.00% | 9.00% | 9.00% |
+| 毛利率 | % | 31.51% | 30.95% | 31.11% | 31.00% | 31.00% | 31.00% |
+| | | | | | | | |
+| 三、分部间抵消 | 亿元 | -25.14 | (29.48) | (34.64) | (37.43) | (42.02) | (48.45) |
+| 同比 | % | 17.32% | 17.27% | 17.50% | 8.06% | 12.26% | 15.31% |
+| 毛利率 | % | -3.39% | -2.05% | -1.61% | -2.0% | -2.0% | -2.0% |
+| 分部抵消营收占工业比例 | % | 28.32% | 29.96% | 31.27% | 33.0% | 34.0% | 35.0% |
+
+资料来源:Wind, 诚通证券研究所
+
+
+
+综上,我们预测公司 2024-2026 年,营业收入分别为 187.7/203.3/222.7 亿元, 分别同比增 5.1%/8.3%/9.5%;归母净利润分别为 16.7/19.4/22.6 亿元,分别同比增 $ {0.3}\% /{15.8}\% /{16.7}\% $ ; 每股 EPS 分别为 1.22/1.41/1.65 元; 毛利率分别为 44.5%/45.5%/46.5%。`,
+ result: [
+ `## 4.1、关键假设及盈利预测
+
+公司医药工业产品线按治疗领域分心血管类、补益类、清热类、妇科类和其他药品,商业分部包含自有产品销售,相应有分部间抵消,我们分别给予营收增速和毛利率假设, 如下:
+
+1)心脑血管类:心脑血管类为公司核心优势产品,产品包括安宫牛黄丸、牛黄清心丸、同仁堂大活络丸等,2021-2023 年心脑血管类产品营收增速逐年下滑, 毛利率受主要原材料牛黄和麝香价格涨幅较大影响,毛利率承压。我们分别假设 2024-2026 年,心脑血管类产品营收增速分别为 0%、8%和 10%,2025 年受消费上升带动开始恢复性增长,毛利率分别为 47%、50%和 52%,毛利率逐年提升,反映牛黄进口试点后,牛黄原料成本压力缓解。
+
+2)补益类:补益类是公司第二大产品线,包括六味地黄丸、五子衍宗丸等。 我们分别假设 2024-2026 年补益类产品营收年增长 8%、10%和 12%,毛利率均保持稳定为 37.5%。
+
+3)妇科类:妇科类产品包括乌鸡白凤丸、坤宝丸等,历年销售比较平稳。我们假设 2024-2026 年妇科类产品年增长 5%,毛利率维持稳定在 42%。
+
+4)清热类:清热类产品与流行性疾病相关,2023 年为流感大年,感冒清热类产品销售相对旺盛,基数较高。我们假设 2024-2026 年清热类产品年增长-15%、8% 和 10%, 2024 年负增长, 反映上 2023 年基数较高和 2024 年流行性疾病小年影响, 毛利率稳定为 35.0%。
+
+5)其他产品:我们假设 2024-2026 年其他中药品种营收年增长 5%、10%和 15%, 毛利率稳定保持 41%。
+
+6)医药商业:医药商业营收增长主要是旗下同仁堂商业零售门店带动, 2023-2024H1 门店新开显著提速,2024 年上半年新开 116 家门店。我们假设 2024-2026 年医药商业年均增长 9%,毛利率保持 31%水平不变。
+
+7)分部抵消:公司医药商业销售自产药品比例逐年提升,2023 年分部抵消 34.6 亿元,占医药工业营收 31.3%左右,我们假设 2024-2026 年,分部间抵消占医药工业营收分别为 33%、34%和 35%,毛利率为 -2%。
+
+表 4:同仁堂主营业务关键假设及营收拆分`,
+
+ `## 4.1、关键假设及盈利预测
+| 同仁堂经营拆分: | 单位 | 2021A | 2022A | 2023A | 2024E | 2025E | 2026E |
+| --- | --- | --- | --- | --- | --- | --- | --- |
+| 合并营业收入 | 亿元 | 146.03 | 153.72 | 178.61 | 187.68 | 203.30 | 222.68 |
+| 同比 | % | 13.86% | 5.27% | 16.19% | 5.08% | 8.33% | 9.53% |
+| 毛利率 | % | 47.62% | 48.80% | 47.29% | 44.53% | 45.50% | 46.46% |
+| | | | | | | | |
+| 分产品 | | | | | | | |
+| 一、医药工业分部 | 亿元 | 88.76 | 98.40 | 110.79 | 113.42 | 123.59 | 138.44 |
+| 同比 | % | 15.99% | 10.86% | 12.59% | 2.38% | 8.96% | 12.02% |
+| 毛利率 | % | 48.13% | 48.95% | 46.96% | 42.50% | 43.63% | 44.32% |
+| 分细分产品: | | | | | | | |
+| 1、母公司生产:心脑血管类(安宫、清心、大活络等) | 亿元 | 36.29 | 40.63 | 43.88 | 43.88 | 47.39 | 52.13 |
+| 同比 | % | 20.80% | 11.97% | 8.00% | 0.00% | 8.00% | 10.00% |
+| 毛利率 | $ \% $ | 59.96% | 61.20% | 57.62% | 47.00% | 50.00% | 52.00% |
+| | | | | | | | |
+| 2、补益类(六味、金匮、五子衍宗) | | 14.56 | 15.67 | 17.30 | 18.68 | 20.55 | 23.02 |
+| 同比 | % | 2.86% | 7.62% | 10.40% | 8.00% | 10.00% | 12.00% |
+| 毛利率 | $ \% $ | 42.45% | 43.00% | 37.39% | 37.50% | 37.50% | 37.50% |
+| | | | | | | | |
+| 3、妇科类(乌鸡白凤丸、坤宝丸) | | 3.80 | 3.48 | 3.77 | 3.96 | 4.15 | 4.36 |
+| 同比 | % | 23.83% | -8.38% | 8.28% | 5.00% | 5.00% | 5.00% |
+| 毛利率 | % | 40.16% | 38.12% | 42.38% | 42.00% | 42.00% | 42.00% |
+| | | | | | | | |
+| 4、清热类(感冒清热颗粒、牛黄解毒) | 亿元 | 5.24 | 5.29 | 6.14 | 5.22 | 5.64 | 6.20 |
+| 同比 | % | 5.19% | 0.86% | 16.07% | -15.00% | 8.00% | 10.00% |
+| 毛利率 | $ \% $ | 36.09% | 34.39% | 34.97% | 35.00% | 35.00% | 35.00% |
+| | | | | | | | |
+| 5、其他中药品种 | 亿元 | 28.87 | 33.33 | 39.70 | 41.69 | 45.85 | 52.73 |
+| 同比 | % | 18.90% | 15.45% | 19.11% | 5.00% | 10.00% | 15.00% |`,
+
+ `## 4.1、关键假设及盈利预测
+| 同仁堂经营拆分: | 单位 | 2021A | 2022A | 2023A | 2024E | 2025E | 2026E |
+| --- | --- | --- | --- | --- | --- | --- | --- |
+| 毛利率 | $ \% $ | 39.36% | 40.25% | 41.65% | 41.00% | 41.00% | 41.00% |
+| | | | | | | | |
+| 二、商业分部(同仁堂商业) | 亿元 | 82.41 | 84.80 | 102.5 | 111.7 | 121.7 | 132.7 |
+| 同比 | % | 12.64% | 2.90% | 20.83% | 9.00% | 9.00% | 9.00% |
+| 毛利率 | % | 31.51% | 30.95% | 31.11% | 31.00% | 31.00% | 31.00% |
+| | | | | | | | |
+| 三、分部间抵消 | 亿元 | -25.14 | (29.48) | (34.64) | (37.43) | (42.02) | (48.45) |
+| 同比 | % | 17.32% | 17.27% | 17.50% | 8.06% | 12.26% | 15.31% |
+| 毛利率 | % | -3.39% | -2.05% | -1.61% | -2.0% | -2.0% | -2.0% |
+| 分部抵消营收占工业比例 | % | 28.32% | 29.96% | 31.27% | 33.0% | 34.0% | 35.0% |
+
+资料来源:Wind, 诚通证券研究所
+
+综上,我们预测公司 2024-2026 年,营业收入分别为 187.7/203.3/222.7 亿元, 分别同比增 5.1%/8.3%/9.5%;归母净利润分别为 16.7/19.4/22.6 亿元,分别同比增 $ {0.3}\% /{15.8}\% /{16.7}\% $ ; 每股 EPS 分别为 1.22/1.41/1.65 元; 毛利率分别为 44.5%/45.5%/46.5%。`
+ ]
+ };
+
+ const { chunks } = splitText2Chunks({
+ text: mock.text,
+ chunkSize: 1000
+ });
+
+ expect(chunks).toEqual(mock.result);
+});
diff --git a/test/cases/global/core/app/jsonschema.test.ts b/test/cases/global/core/app/jsonschema.test.ts
index e16e20fa2..6a4c3e90b 100644
--- a/test/cases/global/core/app/jsonschema.test.ts
+++ b/test/cases/global/core/app/jsonschema.test.ts
@@ -27,7 +27,7 @@ describe('jsonSchema2NodeInput', () => {
valueType: 'string',
toolDescription: 'name',
required: true,
- renderTypeList: ['input']
+ renderTypeList: ['input', 'reference']
},
{
key: 'select',
@@ -54,7 +54,7 @@ describe('jsonSchema2NodeInput', () => {
valueType: 'number',
toolDescription: 'age',
required: true,
- renderTypeList: ['numberInput'],
+ renderTypeList: ['numberInput', 'reference'],
max: 100,
min: 0
},
@@ -72,7 +72,7 @@ describe('jsonSchema2NodeInput', () => {
valueType: 'object',
toolDescription: 'object',
required: false,
- renderTypeList: ['JSONEditor']
+ renderTypeList: ['JSONEditor', 'reference']
},
{
key: 'strArr',
@@ -80,7 +80,7 @@ describe('jsonSchema2NodeInput', () => {
valueType: 'arrayString',
toolDescription: 'strArr',
required: false,
- renderTypeList: ['JSONEditor']
+ renderTypeList: ['JSONEditor', 'reference']
},
{
key: 'numArr',
@@ -88,7 +88,7 @@ describe('jsonSchema2NodeInput', () => {
valueType: 'arrayNumber',
toolDescription: 'numArr',
required: false,
- renderTypeList: ['JSONEditor']
+ renderTypeList: ['JSONEditor', 'reference']
},
{
key: 'boolArr',
@@ -96,7 +96,7 @@ describe('jsonSchema2NodeInput', () => {
valueType: 'arrayBoolean',
toolDescription: 'boolArr',
required: false,
- renderTypeList: ['JSONEditor']
+ renderTypeList: ['JSONEditor', 'reference']
},
{
key: 'objArr',
@@ -104,7 +104,7 @@ describe('jsonSchema2NodeInput', () => {
valueType: 'arrayObject',
toolDescription: 'objArr',
required: false,
- renderTypeList: ['JSONEditor']
+ renderTypeList: ['JSONEditor', 'reference']
},
{
key: 'anyArr',
@@ -112,7 +112,7 @@ describe('jsonSchema2NodeInput', () => {
valueType: 'arrayAny',
toolDescription: 'anyArr',
required: false,
- renderTypeList: ['JSONEditor']
+ renderTypeList: ['JSONEditor', 'reference']
}
];
const result = jsonSchema2NodeInput(jsonSchema);
| |