From 324aaae769f7697e965a947eda755a02f944c073 Mon Sep 17 00:00:00 2001 From: Archer <545436317@qq.com> Date: Wed, 27 Aug 2025 00:08:22 +0800 Subject: [PATCH] fix: ai response test (#5544) * fix: ai response test * fix: skip edge check * fix: app list * fix: toolset conflict interactive node * fix: username show --- document/content/docs/upgrading/4-12/4122.mdx | 3 +- document/data/doc-last-modified.json | 2 +- packages/global/common/error/utils.ts | 5 +++ packages/global/core/app/mcpTools/utils.ts | 2 +- packages/service/core/ai/llm/request.ts | 4 -- .../workflow/dispatch/ai/agent/toolCall.ts | 2 +- .../service/core/workflow/dispatch/ai/chat.ts | 3 +- .../service/core/workflow/dispatch/index.ts | 39 ++++++++++++++----- .../workflow/dispatch/tools/codeSandbox.ts | 1 - .../service/core/workflow/dispatch/utils.ts | 13 +++++-- packages/service/core/workflow/utils.ts | 4 +- .../src/pageComponents/chat/slider/index.tsx | 3 +- projects/app/src/pages/api/core/app/list.ts | 5 ++- .../api/core/app/mcpTools/getChildren.ts | 12 +++++- projects/app/src/web/core/app/api/plugin.ts | 11 ++++-- 15 files changed, 75 insertions(+), 34 deletions(-) diff --git a/document/content/docs/upgrading/4-12/4122.mdx b/document/content/docs/upgrading/4-12/4122.mdx index a9165b2ea..97a2c1e06 100644 --- a/document/content/docs/upgrading/4-12/4122.mdx +++ b/document/content/docs/upgrading/4-12/4122.mdx @@ -7,7 +7,7 @@ description: 'FastGPT V4.12.2 更新说明' ### 1. 更新镜像: -- 更新 FastGPT 镜像tag: v4.12.2 +- 更新 FastGPT 镜像tag: v4.12.2-fix - 更新 FastGPT 商业版镜像tag: v4.12.2 - 更新 fastgpt-plugin 镜像 tag: v0.1.11 - mcp_server 无需更新 @@ -42,6 +42,7 @@ description: 'FastGPT V4.12.2 更新说明' 8. 工作流,添加团队应用,搜索无效。 9. 应用版本,ref 字段错误,导致无法正常使用。 10. Oceanbase 批量插入时,未正确返回插入的 id。 +11. 交互节点与工具集存在冲突,导致交互节点后工具集无法正常使用。 ## 🔨 工具更新 diff --git a/document/data/doc-last-modified.json b/document/data/doc-last-modified.json index fcafdac5d..29cc02f82 100644 --- a/document/data/doc-last-modified.json +++ b/document/data/doc-last-modified.json @@ -104,7 +104,7 @@ "document/content/docs/upgrading/4-11/4111.mdx": "2025-08-07T22:49:09+08:00", "document/content/docs/upgrading/4-12/4120.mdx": "2025-08-12T22:45:19+08:00", "document/content/docs/upgrading/4-12/4121.mdx": "2025-08-15T22:53:06+08:00", - "document/content/docs/upgrading/4-12/4122.mdx": "2025-08-26T17:29:42+08:00", + "document/content/docs/upgrading/4-12/4122.mdx": "2025-08-26T23:08:11+08:00", "document/content/docs/upgrading/4-8/40.mdx": "2025-08-02T19:38:37+08:00", "document/content/docs/upgrading/4-8/41.mdx": "2025-08-02T19:38:37+08:00", "document/content/docs/upgrading/4-8/42.mdx": "2025-08-02T19:38:37+08:00", diff --git a/packages/global/common/error/utils.ts b/packages/global/common/error/utils.ts index c13c8e266..c75e4c87f 100644 --- a/packages/global/common/error/utils.ts +++ b/packages/global/common/error/utils.ts @@ -18,6 +18,11 @@ export const getErrText = (err: any, def = ''): any => { return ERROR_RESPONSE[msg].message; } + // Axios special + if (err?.errors && Array.isArray(err.errors) && err.errors.length > 0) { + return err.errors[0].message; + } + // msg && console.log('error =>', msg); return replaceSensitiveText(msg); }; diff --git a/packages/global/core/app/mcpTools/utils.ts b/packages/global/core/app/mcpTools/utils.ts index d9374a7ae..38e24c311 100644 --- a/packages/global/core/app/mcpTools/utils.ts +++ b/packages/global/core/app/mcpTools/utils.ts @@ -61,7 +61,7 @@ export const getMCPToolRuntimeNode = ({ parentId: string; }): RuntimeNodeItemType => { return { - nodeId: getNanoid(16), + nodeId: getNanoid(), flowNodeType: FlowNodeTypeEnum.tool, avatar, intro: tool.description, diff --git a/packages/service/core/ai/llm/request.ts b/packages/service/core/ai/llm/request.ts index 238ff44e9..d5188930a 100644 --- a/packages/service/core/ai/llm/request.ts +++ b/packages/service/core/ai/llm/request.ts @@ -67,8 +67,6 @@ export const createLLMResponse = async ( const { body, custonHeaders, userKey } = args; const { messages, useVision, requestOrigin, tools, toolCallMode } = body; - const modelData = getLLMModel(body.model); - // Messages process const requestMessages = await loadRequestMessages({ messages, @@ -475,13 +473,11 @@ type LLMRequestBodyType = Omit({ - reasoning, retainDatasetCite, useVision, requestOrigin, diff --git a/packages/service/core/workflow/dispatch/ai/agent/toolCall.ts b/packages/service/core/workflow/dispatch/ai/agent/toolCall.ts index 5dd264bbf..07c01e043 100644 --- a/packages/service/core/workflow/dispatch/ai/agent/toolCall.ts +++ b/packages/service/core/workflow/dispatch/ai/agent/toolCall.ts @@ -287,7 +287,6 @@ export const runToolCall = async ( body: { model: toolModel.model, stream, - reasoning: aiChatReasoning, messages: filterMessages, tool_choice: 'auto', toolCallMode: toolModel.toolChoice ? 'toolChoice' : 'prompt', @@ -308,6 +307,7 @@ export const runToolCall = async ( isAborted: () => res?.closed, userKey: externalProvider.openaiAccount, onReasoning({ text }) { + if (!aiChatReasoning) return; workflowStreamResponse?.({ write, event: SseResponseEventEnum.answer, diff --git a/packages/service/core/workflow/dispatch/ai/chat.ts b/packages/service/core/workflow/dispatch/ai/chat.ts index bf93f93a3..d7275ab03 100644 --- a/packages/service/core/workflow/dispatch/ai/chat.ts +++ b/packages/service/core/workflow/dispatch/ai/chat.ts @@ -184,7 +184,6 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise res?.closed, onReasoning({ text }) { + if (!aiChatReasoning) return; workflowStreamResponse?.({ write, event: SseResponseEventEnum.answer, @@ -210,6 +210,7 @@ export const dispatchChatCompletion = async (props: ChatProps): Promise(); + private skipNodeQueue: { node: RuntimeNodeItemType; skippedNodeIdList: Set }[] = []; private runningNodeCount = 0; private maxConcurrency: number; private resolve: (e: WorkflowQueue) => void; @@ -198,13 +201,17 @@ export async function dispatchWorkFlow(data: Props): Promise 0 && !this.nodeInteractiveResponse) { + this.processSkipNodes(); + } else { + this.resolve(this); + } return; } @@ -224,12 +231,26 @@ export async function dispatchWorkFlow(data: Props): Promise { this.runningNodeCount--; - this.processNextNode(); + this.processActiveNode(); }); } // 兜底,除非极端情况,否则不可能触发 else { - this.processNextNode(); + this.processActiveNode(); + } + } + + private addSkipNode(node: RuntimeNodeItemType, skippedNodeIdList: Set) { + this.skipNodeQueue.push({ node, skippedNodeIdList }); + } + private processSkipNodes() { + const skipItem = this.skipNodeQueue.shift(); + if (skipItem) { + this.checkNodeCanRun(skipItem.node, skipItem.skippedNodeIdList).finally(() => { + this.processActiveNode(); + }); + } else { + this.processActiveNode(); } } @@ -695,9 +716,9 @@ export async function dispatchWorkFlow(data: Props): Promise this.checkNodeCanRun(node, skippedNodeIdList)) - ); + nextStepSkipNodes.forEach((node) => { + this.addSkipNode(node, skippedNodeIdList); + }); // Run next nodes nextStepActiveNodes.forEach((node) => { diff --git a/packages/service/core/workflow/dispatch/tools/codeSandbox.ts b/packages/service/core/workflow/dispatch/tools/codeSandbox.ts index 4fb9b9294..e672b9026 100644 --- a/packages/service/core/workflow/dispatch/tools/codeSandbox.ts +++ b/packages/service/core/workflow/dispatch/tools/codeSandbox.ts @@ -5,7 +5,6 @@ import axios from 'axios'; import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runtime/constants'; import { SandboxCodeTypeEnum } from '@fastgpt/global/core/workflow/template/system/sandbox/constants'; import { getErrText } from '@fastgpt/global/common/error/utils'; -import { getNodeErrResponse } from '../utils'; type RunCodeType = ModuleDispatchProps<{ [NodeInputKeyEnum.codeType]: string; diff --git a/packages/service/core/workflow/dispatch/utils.ts b/packages/service/core/workflow/dispatch/utils.ts index c308c384e..e17282594 100644 --- a/packages/service/core/workflow/dispatch/utils.ts +++ b/packages/service/core/workflow/dispatch/utils.ts @@ -210,17 +210,22 @@ export const rewriteRuntimeWorkFlow = async ({ if (!app) continue; const toolList = await getMCPChildren(app); - for (const tool of toolList) { + const parentId = mcpToolsetVal.toolId ?? toolSetNode.pluginId; + toolList.forEach((tool, index) => { const newToolNode = getMCPToolRuntimeNode({ avatar: toolSetNode.avatar, tool, // New ?? Old - parentId: mcpToolsetVal.toolId ?? toolSetNode.pluginId + parentId }); + newToolNode.nodeId = `${parentId}${index}`; // ID 不能随机,否则下次生成时候就和之前的记录对不上 - nodes.push({ ...newToolNode, name: `${toolSetNode.name}/${tool.name}` }); + nodes.push({ + ...newToolNode, + name: `${toolSetNode.name}/${tool.name}` + }); pushEdges(newToolNode.nodeId); - } + }); } } diff --git a/packages/service/core/workflow/utils.ts b/packages/service/core/workflow/utils.ts index b78152f64..7c65df375 100644 --- a/packages/service/core/workflow/utils.ts +++ b/packages/service/core/workflow/utils.ts @@ -48,7 +48,7 @@ export async function getSystemToolRunTimeNodeFromSystemToolset({ (item) => item.parentId === systemToolId && item.isActive !== false ); const nodes = await Promise.all( - children.map(async (child) => { + children.map(async (child, index) => { const toolListItem = toolSetNode.toolConfig?.systemToolSet?.toolList.find( (item) => item.toolId === child.id ); @@ -70,7 +70,7 @@ export async function getSystemToolRunTimeNodeFromSystemToolset({ name: toolListItem?.name || parseI18nString(tool.name, lang), intro: toolListItem?.description || parseI18nString(tool.intro, lang), flowNodeType: FlowNodeTypeEnum.tool, - nodeId: getNanoid(), + nodeId: `${toolSetNode.nodeId}${index}`, toolConfig: { systemTool: { toolId: child.id diff --git a/projects/app/src/pageComponents/chat/slider/index.tsx b/projects/app/src/pageComponents/chat/slider/index.tsx index 43669c352..d5837f146 100644 --- a/projects/app/src/pageComponents/chat/slider/index.tsx +++ b/projects/app/src/pageComponents/chat/slider/index.tsx @@ -362,7 +362,6 @@ const BottomSection = () => { const { userInfo } = useUserStore(); const isLoggedIn = !!userInfo; const avatar = userInfo?.avatar; - const username = userInfo?.username; const isAdmin = !!userInfo?.team.permission.hasManagePer; const isShare = pathname === '/chat/share'; @@ -448,7 +447,7 @@ const BottomSection = () => { fontWeight={500} minW={0} > - {username} + {userInfo?.team?.memberName} diff --git a/projects/app/src/pages/api/core/app/list.ts b/projects/app/src/pages/api/core/app/list.ts index b65d8b0cd..17839ef12 100644 --- a/projects/app/src/pages/api/core/app/list.ts +++ b/projects/app/src/pages/api/core/app/list.ts @@ -106,7 +106,9 @@ async function handler(req: ApiRequestProps): Promise item.resourceId) } }; const appPerQuery = teamPer.isOwner - ? {} + ? { + parentId: parentId ? parseParentIdInMongo(parentId) : null + } : parentId ? { $or: [idList, parseParentIdInMongo(parentId)] @@ -138,6 +140,7 @@ async function handler(req: ApiRequestProps): Promise, _res: ApiResponseType ): Promise { - const { id } = req.query; + const { id, searchKey } = req.query; const app = await MongoApp.findOne({ _id: id }).lean(); @@ -28,6 +30,12 @@ async function handler( if (app.type !== AppTypeEnum.toolSet) return Promise.reject(new UserError('the parent is not a mcp toolset')); - return getMCPChildren(app); + return (await getMCPChildren(app)).filter((item) => { + if (searchKey && searchKey.trim() !== '') { + const regx = new RegExp(replaceRegChars(searchKey.trim()), 'i'); + return regx.test(item.name); + } + return true; + }); } export default NextAPI(handler); diff --git a/projects/app/src/web/core/app/api/plugin.ts b/projects/app/src/web/core/app/api/plugin.ts index 703435017..323bf077a 100644 --- a/projects/app/src/web/core/app/api/plugin.ts +++ b/projects/app/src/web/core/app/api/plugin.ts @@ -29,7 +29,10 @@ import type { getToolVersionListProps, getToolVersionResponse } from '@/pages/api/core/app/plugin/getVersionList'; -import type { McpGetChildrenmResponse } from '@/pages/api/core/app/mcpTools/getChildren'; +import type { + McpGetChildrenmQuery, + McpGetChildrenmResponse +} from '@/pages/api/core/app/mcpTools/getChildren'; /* ============ team plugin ============== */ export const getTeamPlugTemplates = async (data?: { @@ -40,7 +43,7 @@ export const getTeamPlugTemplates = async (data?: { // handle get mcptools const app = await getAppDetailById(data.parentId); if (app.type === AppTypeEnum.toolSet) { - const children = await getMcpChildren(data.parentId); + const children = await getMcpChildren({ id: data.parentId, searchKey: data.searchKey }); return children.map((item) => ({ ...item, flowNodeType: FlowNodeTypeEnum.tool, @@ -109,8 +112,8 @@ 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 }); +export const getMcpChildren = (data: McpGetChildrenmQuery) => + GET('/core/app/mcpTools/getChildren', data); /* ============ http plugin ============== */ export const postCreateHttpPlugin = (data: createHttpPluginBody) =>