From 036af0f1bef17c6adfc4f2cfd8a0ddc47c75a9df Mon Sep 17 00:00:00 2001 From: YeYuheng <57035043+YYH211@users.noreply.github.com> Date: Thu, 23 Apr 2026 18:02:28 +0800 Subject: [PATCH] helper-error (#6802) * helper-error * helper-error * helper-error * helper-error * reset helperbot fe --------- Co-authored-by: archer <545436317@qq.com> --- document/data/doc-last-modified.json | 2 +- .../components/core/chat/HelperBot/index.tsx | 4 +- .../api/core/chat/helperBot/completions.ts | 168 +++++++++++------- 3 files changed, 103 insertions(+), 71 deletions(-) diff --git a/document/data/doc-last-modified.json b/document/data/doc-last-modified.json index 1e20ff4a2f..926a20a7b7 100644 --- a/document/data/doc-last-modified.json +++ b/document/data/doc-last-modified.json @@ -425,4 +425,4 @@ "document/content/docs/use-cases/external-integration/wecom.mdx": "2025-12-10T20:07:05+08:00", "document/content/docs/use-cases/index.en.mdx": "2026-02-26T22:14:30+08:00", "document/content/docs/use-cases/index.mdx": "2025-07-24T14:23:04+08:00" -} \ No newline at end of file +} diff --git a/projects/app/src/components/core/chat/HelperBot/index.tsx b/projects/app/src/components/core/chat/HelperBot/index.tsx index ec5f54922d..5781086f5e 100644 --- a/projects/app/src/components/core/chat/HelperBot/index.tsx +++ b/projects/app/src/components/core/chat/HelperBot/index.tsx @@ -299,7 +299,7 @@ const ChatBox = ({ type, metadata, onApply, ChatBoxRef, ...props }: HelperBotPro const abortSignal = new AbortController(); chatController.current = abortSignal; - const { responseText } = await streamFetch({ + const response = await streamFetch({ url: '/api/core/chat/helperBot/completions', data: { chatId, @@ -320,11 +320,9 @@ const ChatBox = ({ type, metadata, onApply, ChatBoxRef, ...props }: HelperBotPro abortCtrl: abortSignal }); } catch (error) { - console.error(error); setChatRecords((state) => state.map((item, index) => { if (index !== state.length - 1 || item.obj !== ChatRoleEnum.AI) return item; - return { ...item, value: [ diff --git a/projects/app/src/pages/api/core/chat/helperBot/completions.ts b/projects/app/src/pages/api/core/chat/helperBot/completions.ts index 1633ee315f..7fe9e20cb5 100644 --- a/projects/app/src/pages/api/core/chat/helperBot/completions.ts +++ b/projects/app/src/pages/api/core/chat/helperBot/completions.ts @@ -12,82 +12,116 @@ import { pushChatRecords } from '@fastgpt/service/core/chat/HelperBot/utils'; import { getLocale } from '@fastgpt/service/common/middle/i18n'; import { authFrequencyLimit } from '@fastgpt/service/common/system/frequencyLimit/utils'; import { addSeconds } from 'date-fns'; -import { getLastInteractiveValue } from '@fastgpt/global/core/workflow/runtime/utils'; -import { ChatRoleEnum } from '@fastgpt/global/core/chat/constants'; +import { sseErrRes } from '@fastgpt/service/common/response'; +import { getLogger, LogCategories } from '@fastgpt/service/common/logger'; export type completionsBody = HelperBotCompletionsParamsType; async function handler(req: ApiRequestProps, res: ApiResponseType) { - const { chatId, chatItemId, query, files, metadata } = HelperBotCompletionsParamsSchema.parse( - req.body - ); + const logger = getLogger(LogCategories.MODULE.AI.HELPERBOT); + const setSSEHeaders = () => { + const headers: Record = { + Connection: 'keep-alive', + 'Content-Type': 'text/event-stream;charset=utf-8', + 'Access-Control-Allow-Origin': '*', + 'X-Accel-Buffering': 'no', + 'Cache-Control': 'no-cache, no-transform' + }; + Object.entries(headers).forEach(([key, value]) => { + res.setHeader(key, value); + }); + }; - const { teamId, tmbId, userId, isRoot } = await authCert({ req, authToken: true }); + // keep consistent with SSE APIs, otherwise stream consumer may treat response as non-SSE + setSSEHeaders(); - // Limit - await authFrequencyLimit({ - eventId: `${tmbId}-helperBot-completions`, - maxAmount: 10, - expiredTime: addSeconds(new Date(), 60) - }).catch((err) => { - return Promise.reject('Frequency limit exceeded'); - }); + const parseResult = HelperBotCompletionsParamsSchema.safeParse(req.body); - const histories = await MongoHelperBotChatItem.find({ - userId, - chatId - }) - .sort({ _id: -1 }) - .limit(40) - .lean(); - histories.reverse(); - - const workflowResponseWrite = getWorkflowResponseWrite({ - res, - detail: true, - streamResponse: true, - id: chatId, - showNodeStatus: true - }); - - // 执行不同逻辑 - const fn = dispatchMap[metadata.type]; - if (!fn) { - return Promise.reject('Invalid helper bot type'); + if (!parseResult.success) { + sseErrRes(res, parseResult.error); + return res.end(); } - const result = await fn({ - query, - files, - data: metadata.data, - histories, - workflowResponseWrite, - user: { - teamId, - tmbId, - userId, - isRoot, - lang: getLocale(req) - } - }); - // Save chat - await pushChatRecords({ - type: metadata.type, - userId, - chatId, - chatItemId, - query, - files, - aiResponse: result.aiResponse - }); - // Push usage - // pushHelperBotUsage({ - // teamId, - // tmbId, - // model: result.usage.model, - // inputTokens: result.usage.inputTokens, - // outputTokens: result.usage.outputTokens - // }); + const { chatId, chatItemId, query, files, metadata } = parseResult.data; + + try { + const { teamId, tmbId, userId, isRoot } = await authCert({ req, authToken: true }); + + // Limit + await authFrequencyLimit({ + eventId: `${tmbId}-helperBot-completions`, + maxAmount: 10, + expiredTime: addSeconds(new Date(), 60) + }).catch(() => { + return Promise.reject('Frequency limit exceeded'); + }); + + const histories = await MongoHelperBotChatItem.find({ + userId, + chatId + }) + .sort({ _id: -1 }) + .limit(40) + .lean(); + histories.reverse(); + + const workflowResponseWrite = getWorkflowResponseWrite({ + res, + detail: true, + streamResponse: true, + id: chatId, + showNodeStatus: true + }); + + // 执行不同逻辑 + const fn = dispatchMap[metadata.type]; + if (!fn) { + return Promise.reject('Invalid helper bot type'); + } + const result = await fn({ + query, + files, + data: metadata.data, + histories, + workflowResponseWrite, + user: { + teamId, + tmbId, + userId, + isRoot, + lang: getLocale(req) + } + }); + + // Save chat + await pushChatRecords({ + type: metadata.type, + userId, + chatId, + chatItemId, + query, + files, + aiResponse: result.aiResponse + }); + // Push usage + // pushHelperBotUsage({ + // teamId, + // tmbId, + // model: result.usage.model, + // inputTokens: result.usage.inputTokens, + // outputTokens: result.usage.outputTokens + // }); + } catch (error) { + logger.error('HelperBot completions failed', { + error, + chatId, + chatItemId, + metadata + }); + sseErrRes(res, error); + } + + res.end(); } export default NextAPI(handler);