mirror of
https://github.com/labring/FastGPT.git
synced 2026-05-08 01:08:43 +08:00
fix: adapt systemTool (#6817)
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
---
|
||||
title: 'V4.14.14'
|
||||
description: 'FastGPT V4.14.14 Release Notes'
|
||||
---
|
||||
|
||||
## Upgrade Guide
|
||||
|
||||
### 1. Update image tags
|
||||
|
||||
- Update fastgpt-app (FastGPT main service) image tag to: v4.14.14
|
||||
- Update fastgpt-pro (FastGPT commercial) image tag to: v4.14.14
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
|
||||
|
||||
## ⚙️ Optimizations
|
||||
|
||||
1. Personal WeChat publishing channel: optimized polling strategy by decoupling pull from reply, preventing blocking under high message volume.
|
||||
2. Added environment variable `WECHAT_CHANNEL_CONCURRENCY` (default 1000) to control the WeChat channel poll worker concurrency. Recommended to set ≥ peak online channel count.
|
||||
3. Improved internal network address detection.
|
||||
4. Added compatibility for DeepSeek tool calling combined with thinking mode to avoid 400 errors from the API.
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
title: 'V4.14.14'
|
||||
description: 'FastGPT V4.14.14 Release Notes'
|
||||
---
|
||||
|
||||
## Upgrade Guide
|
||||
|
||||
### 1. Update image tags
|
||||
|
||||
- Update fastgpt-app (FastGPT main service) image tag to: v4.14.15
|
||||
- Update fastgpt-pro (FastGPT commercial) image tag to: v4.14.15
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
|
||||
1. Fixed compatibility for legacy system tools.
|
||||
2. Fixed an issue where selecting a system component as a system tool caused errors.
|
||||
|
||||
## ⚙️ Optimizations
|
||||
@@ -0,0 +1,20 @@
|
||||
---
|
||||
title: 'V4.14.15'
|
||||
description: 'FastGPT V4.14.15 更新说明'
|
||||
---
|
||||
|
||||
## 升级指南
|
||||
|
||||
建议 4.14.8 以后的用户直接升级到该版本使用。
|
||||
|
||||
### 1. 更新镜像 tag
|
||||
|
||||
- 更新 fastgpt-app(fastgpt 主服务) 镜像 tag: v4.14.15
|
||||
- 更新 fastgpt-pro(fastgpt 商业版) 镜像 tag: v4.14.15
|
||||
|
||||
## 🐛 修复
|
||||
|
||||
1. 修复兼容旧版的系统工具。
|
||||
2. 修复选中系统组件为系统工具异常。
|
||||
|
||||
## ⚙️ 优化
|
||||
@@ -118,6 +118,8 @@ description: FastGPT Toc
|
||||
- [/en/docs/self-host/upgrading/4-14/41411](/en/docs/self-host/upgrading/4-14/41411)
|
||||
- [/en/docs/self-host/upgrading/4-14/41412](/en/docs/self-host/upgrading/4-14/41412)
|
||||
- [/en/docs/self-host/upgrading/4-14/41413](/en/docs/self-host/upgrading/4-14/41413)
|
||||
- [/en/docs/self-host/upgrading/4-14/41414](/en/docs/self-host/upgrading/4-14/41414)
|
||||
- [/en/docs/self-host/upgrading/4-14/41415](/en/docs/self-host/upgrading/4-14/41415)
|
||||
- [/en/docs/self-host/upgrading/4-14/4142](/en/docs/self-host/upgrading/4-14/4142)
|
||||
- [/en/docs/self-host/upgrading/4-14/4143](/en/docs/self-host/upgrading/4-14/4143)
|
||||
- [/en/docs/self-host/upgrading/4-14/4144](/en/docs/self-host/upgrading/4-14/4144)
|
||||
|
||||
@@ -118,6 +118,7 @@ description: FastGPT 文档目录
|
||||
- [/docs/self-host/upgrading/4-14/41412](/docs/self-host/upgrading/4-14/41412)
|
||||
- [/docs/self-host/upgrading/4-14/41413](/docs/self-host/upgrading/4-14/41413)
|
||||
- [/docs/self-host/upgrading/4-14/41414](/docs/self-host/upgrading/4-14/41414)
|
||||
- [/docs/self-host/upgrading/4-14/41415](/docs/self-host/upgrading/4-14/41415)
|
||||
- [/docs/self-host/upgrading/4-14/4142](/docs/self-host/upgrading/4-14/4142)
|
||||
- [/docs/self-host/upgrading/4-14/4143](/docs/self-host/upgrading/4-14/4143)
|
||||
- [/docs/self-host/upgrading/4-14/4144](/docs/self-host/upgrading/4-14/4144)
|
||||
|
||||
@@ -251,7 +251,7 @@
|
||||
"document/content/docs/self-host/upgrading/4-14/41481.mdx": "2026-03-09T17:39:53+08:00",
|
||||
"document/content/docs/self-host/upgrading/4-14/4149.en.mdx": "2026-03-23T12:17:04+08:00",
|
||||
"document/content/docs/self-host/upgrading/4-14/4149.mdx": "2026-04-07T21:01:52+08:00",
|
||||
"document/content/docs/self-host/upgrading/4-15/4150.mdx": "2026-04-23T18:02:28+08:00",
|
||||
"document/content/docs/self-host/upgrading/4-15/4150.mdx": "2026-04-24T22:01:29+08:00",
|
||||
"document/content/docs/self-host/upgrading/outdated/40.en.mdx": "2026-03-03T17:39:47+08:00",
|
||||
"document/content/docs/self-host/upgrading/outdated/40.mdx": "2026-03-03T17:39:47+08:00",
|
||||
"document/content/docs/self-host/upgrading/outdated/41.en.mdx": "2026-03-03T17:39:47+08:00",
|
||||
|
||||
@@ -446,7 +446,6 @@ export async function getChildAppPreviewNode({
|
||||
}
|
||||
// http tool
|
||||
else if (source === AppToolSourceEnum.http) {
|
||||
console.log('pluginId', pluginId);
|
||||
const [parentId, ...rest] = pluginId.split('/');
|
||||
const toolName = rest.join('/');
|
||||
const toolset = await MongoApp.findById(parentId).lean();
|
||||
@@ -718,10 +717,14 @@ export const refreshSystemTools = async (): Promise<AppToolTemplateItemType[]> =
|
||||
return concatTools;
|
||||
};
|
||||
|
||||
// toolId: systemTool-id, commercial-id
|
||||
// toolId: systemTool-id, commercial-id, community-id(deprecated, 映射为 systemTool-id)
|
||||
export const getSystemToolById = async (toolId: string): Promise<AppToolTemplateItemType> => {
|
||||
const tools = await getSystemTools();
|
||||
const tool = tools.find((item) => item.id === toolId);
|
||||
// 兼容旧的 community- 前缀,统一归一化为 systemTool-
|
||||
const normalizedId = toolId.startsWith(`${AppToolSourceEnum.community}-`)
|
||||
? `${AppToolSourceEnum.systemTool}-${toolId.slice(AppToolSourceEnum.community.length + 1)}`
|
||||
: toolId;
|
||||
const tool = tools.find((item) => item.id === normalizedId);
|
||||
if (tool) {
|
||||
return cloneDeep(tool);
|
||||
}
|
||||
|
||||
@@ -87,6 +87,7 @@ export async function rewriteAppWorkflowToDetail({
|
||||
const result = await loadToolNode({ id: node.pluginId, versionId: node.version });
|
||||
if (result.success) {
|
||||
const preview = result.data!;
|
||||
node.avatar = preview.avatar ?? node.avatar;
|
||||
node.isFolder = preview.isFolder;
|
||||
node.pluginData = {
|
||||
name: preview.name,
|
||||
|
||||
@@ -50,7 +50,6 @@ export const dispatchRunTool = async (props: RunToolProps): Promise<RunToolRespo
|
||||
runningAppInfo,
|
||||
variables,
|
||||
workflowStreamResponse,
|
||||
|
||||
node: { name, avatar, toolConfig, version, catchError }
|
||||
} = props;
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import type { AppToolRuntimeType } from '@fastgpt/global/core/app/tool/type';
|
||||
import { anyValueDecrypt } from '../../../../common/secret/utils';
|
||||
import { getAppVersionById } from '../../../app/version/controller';
|
||||
import { parseI18nString } from '@fastgpt/global/common/i18n/utils';
|
||||
import { getSystemToolByIdAndVersionId } from '../../../app/tool/controller';
|
||||
|
||||
type RunPluginProps = ModuleDispatchProps<{
|
||||
[NodeInputKeyEnum.forbidStream]?: boolean;
|
||||
@@ -59,7 +60,7 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
|
||||
|
||||
try {
|
||||
// Adapt <= 4.10 system tool
|
||||
const { source, pluginId: formatPluginId } = splitCombineToolId(pluginId);
|
||||
const { source, pluginId: appId } = splitCombineToolId(pluginId);
|
||||
if (source === AppToolSourceEnum.systemTool) {
|
||||
return await dispatchRunTool({
|
||||
...props,
|
||||
@@ -67,7 +68,7 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
|
||||
...props.node,
|
||||
toolConfig: {
|
||||
systemTool: {
|
||||
toolId: formatPluginId
|
||||
toolId: pluginId
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,37 +80,59 @@ export const dispatchRunPlugin = async (props: RunPluginProps): Promise<RunPlugi
|
||||
}
|
||||
|
||||
/*
|
||||
1. Team app
|
||||
2. Admin selected system tool
|
||||
1. Team app (personal): 走 team 权限校验
|
||||
2. Admin selected system tool (commercial): 系统级工具,不做用户态权限校验
|
||||
*/
|
||||
const { files } = chatValue2RuntimePrompt(query);
|
||||
|
||||
// auth workflowTool
|
||||
const toolData = await authWorkflowToolByTmbId({
|
||||
appId: formatPluginId,
|
||||
tmbId: runningAppInfo.tmbId,
|
||||
per: ReadPermissionVal
|
||||
});
|
||||
// 仅在 personal 分支需要 toolData 来判断 pluginDetail 的可见性
|
||||
const toolData =
|
||||
source === AppToolSourceEnum.personal
|
||||
? await authWorkflowToolByTmbId({
|
||||
appId,
|
||||
tmbId: runningAppInfo.tmbId,
|
||||
per: ReadPermissionVal
|
||||
})
|
||||
: undefined;
|
||||
|
||||
const toolVersion = await getAppVersionById({
|
||||
appId: toolData._id,
|
||||
versionId: version,
|
||||
app: toolData
|
||||
});
|
||||
if (source === AppToolSourceEnum.personal && toolData) {
|
||||
const toolVersion = await getAppVersionById({
|
||||
appId: toolData._id,
|
||||
versionId: version,
|
||||
app: toolData
|
||||
});
|
||||
|
||||
workflowTool = {
|
||||
id: String(toolData._id),
|
||||
teamId: toolData.teamId,
|
||||
tmbId: toolData.tmbId,
|
||||
name: parseI18nString(toolData.name, props.lang),
|
||||
avatar: toolData.avatar || '',
|
||||
showStatus: true,
|
||||
currentCost: 0,
|
||||
systemKeyCost: 0,
|
||||
nodes: toolVersion.nodes,
|
||||
edges: toolVersion.edges,
|
||||
hasTokenFee: false
|
||||
};
|
||||
workflowTool = {
|
||||
id: String(toolData._id),
|
||||
teamId: toolData.teamId,
|
||||
tmbId: toolData.tmbId,
|
||||
name: parseI18nString(toolData.name, props.lang),
|
||||
avatar: toolData.avatar || '',
|
||||
showStatus: true,
|
||||
currentCost: 0,
|
||||
systemKeyCost: 0,
|
||||
nodes: toolVersion.nodes,
|
||||
edges: toolVersion.edges,
|
||||
hasTokenFee: false
|
||||
};
|
||||
} else {
|
||||
// commercial: 通过系统工具加载(内部会解析 associatedPluginId 对应的 app 版本)
|
||||
const systemTool = await getSystemToolByIdAndVersionId(pluginId, version);
|
||||
|
||||
workflowTool = {
|
||||
id: systemTool.id,
|
||||
teamId: systemTool.teamId,
|
||||
tmbId: systemTool.tmbId,
|
||||
name: parseI18nString(systemTool.name, props.lang),
|
||||
avatar: systemTool.avatar || '',
|
||||
showStatus: true,
|
||||
currentCost: systemTool.currentCost ?? 0,
|
||||
systemKeyCost: systemTool.systemKeyCost ?? 0,
|
||||
nodes: systemTool.workflow.nodes,
|
||||
edges: systemTool.workflow.edges,
|
||||
hasTokenFee: !!systemTool.hasTokenFee
|
||||
};
|
||||
}
|
||||
|
||||
const outputFilterMap =
|
||||
workflowTool.nodes
|
||||
|
||||
@@ -293,8 +293,7 @@ const MySelect = <T = any,>(
|
||||
<MenuList
|
||||
ref={MenuListRef}
|
||||
className={props.className}
|
||||
minW={0}
|
||||
w={(() => {
|
||||
minW={(() => {
|
||||
const w = ButtonRef.current?.clientWidth;
|
||||
if (w) {
|
||||
return `${w}px !important`;
|
||||
@@ -303,6 +302,7 @@ const MySelect = <T = any,>(
|
||||
? width.map((item) => `${item} !important`)
|
||||
: `${width} !important`;
|
||||
})()}
|
||||
w={'max-content'}
|
||||
px={'6px'}
|
||||
py={'6px'}
|
||||
border={'1px solid #fff'}
|
||||
|
||||
+10
-5
@@ -655,6 +655,15 @@ const NodeVersion = React.memo(function NodeVersion({ node }: { node: FlowNodeIt
|
||||
);
|
||||
}, [node.isLatestVersion, node?.version, node?.versionLabel, t]);
|
||||
|
||||
const ScrollDataWrapper = useCallback(
|
||||
(props: { children: React.ReactNode }) => (
|
||||
<ScrollData minH={'100px'} maxH={'40vh'}>
|
||||
{props.children}
|
||||
</ScrollData>
|
||||
),
|
||||
[ScrollData]
|
||||
);
|
||||
|
||||
return (
|
||||
<MySelect
|
||||
className="nowheel"
|
||||
@@ -667,11 +676,7 @@ const NodeVersion = React.memo(function NodeVersion({ node }: { node: FlowNodeIt
|
||||
variant={'whitePrimaryOutline'}
|
||||
size={'sm'}
|
||||
list={renderVersionList}
|
||||
ScrollData={(props) => (
|
||||
<ScrollData minH={'100px'} maxH={'40vh'}>
|
||||
{props.children}
|
||||
</ScrollData>
|
||||
)}
|
||||
ScrollData={ScrollDataWrapper}
|
||||
valueLabel={valueLabel}
|
||||
/>
|
||||
);
|
||||
|
||||
@@ -150,30 +150,28 @@ export const useChatTest = ({
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [variableList]);
|
||||
|
||||
const CustomChatContainer = useCallback(
|
||||
() =>
|
||||
appDetail.type === AppTypeEnum.workflowTool ? (
|
||||
<Box p={5} pb={16}>
|
||||
<PluginRunBox
|
||||
appId={appId}
|
||||
chatId={chatId}
|
||||
onNewChat={restartChat}
|
||||
onStartChat={startChat}
|
||||
runtimeFileSelectConfig={chatConfig.fileSelectConfig}
|
||||
/>
|
||||
</Box>
|
||||
) : (
|
||||
<ChatBox
|
||||
isReady={isReady}
|
||||
const CustomChatContainer = useMemoizedFn(() =>
|
||||
appDetail.type === AppTypeEnum.workflowTool ? (
|
||||
<Box p={5} pb={16}>
|
||||
<PluginRunBox
|
||||
appId={appId}
|
||||
chatId={chatId}
|
||||
showMarkIcon
|
||||
chatType={ChatTypeEnum.test}
|
||||
enableAutoResume
|
||||
onNewChat={restartChat}
|
||||
onStartChat={startChat}
|
||||
runtimeFileSelectConfig={chatConfig.fileSelectConfig}
|
||||
/>
|
||||
),
|
||||
[appDetail.type, appId, chatId, isReady, restartChat, startChat, chatConfig]
|
||||
</Box>
|
||||
) : (
|
||||
<ChatBox
|
||||
isReady={isReady}
|
||||
appId={appId}
|
||||
chatId={chatId}
|
||||
showMarkIcon
|
||||
chatType={ChatTypeEnum.test}
|
||||
enableAutoResume
|
||||
onStartChat={startChat}
|
||||
/>
|
||||
)
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@@ -6,7 +6,10 @@ 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 { getSystemToolByIdAndVersionId } from '@fastgpt/service/core/app/tool/controller';
|
||||
import {
|
||||
getSystemToolById,
|
||||
getSystemToolByIdAndVersionId
|
||||
} from '@fastgpt/service/core/app/tool/controller';
|
||||
import { AppToolSourceEnum } from '@fastgpt/global/core/app/tool/constants';
|
||||
import { PluginErrEnum } from '@fastgpt/global/common/error/code/plugin';
|
||||
import { Types } from '@fastgpt/service/common/mongo';
|
||||
@@ -35,7 +38,7 @@ async function handler(
|
||||
};
|
||||
}
|
||||
|
||||
const { source, pluginId: formatPluginId, authAppId } = splitCombineToolId(pluginId);
|
||||
const { source, authAppId } = splitCombineToolId(pluginId);
|
||||
|
||||
// System tool plugin
|
||||
if (source === AppToolSourceEnum.systemTool) {
|
||||
@@ -62,7 +65,13 @@ async function handler(
|
||||
});
|
||||
return app._id;
|
||||
} else {
|
||||
return formatPluginId;
|
||||
// Get appId from pluginId
|
||||
const tool = await getSystemToolById(pluginId);
|
||||
|
||||
if (!tool.associatedPluginId) {
|
||||
return Promise.reject(PluginErrEnum.unExist);
|
||||
}
|
||||
return tool.associatedPluginId;
|
||||
}
|
||||
})();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user