helper-error (#6802)

* helper-error

* helper-error

* helper-error

* helper-error

* reset helperbot fe

---------

Co-authored-by: archer <545436317@qq.com>
This commit is contained in:
YeYuheng
2026-04-23 18:02:28 +08:00
committed by GitHub
parent 38a7cb27e5
commit c1cd46789e
4 changed files with 105 additions and 72 deletions
@@ -12,7 +12,8 @@ description: 'FastGPT V4.15.0 更新说明'
## 🐛 修复
1. 阿里云 oss copy 接口。
1. helper-bot 前缀输出 Error 信息
2. 阿里云 oss copy 接口。
## 代码优化
+1 -1
View File
@@ -426,4 +426,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"
}
}
@@ -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: [
@@ -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<completionsBody>, res: ApiResponseType<any>) {
const { chatId, chatItemId, query, files, metadata } = HelperBotCompletionsParamsSchema.parse(
req.body
);
const logger = getLogger(LogCategories.MODULE.AI.HELPERBOT);
const setSSEHeaders = () => {
const headers: Record<string, string> = {
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);