diff --git a/docSite/content/zh-cn/docs/development/upgrading/4101.md b/docSite/content/zh-cn/docs/development/upgrading/4101.md new file mode 100644 index 000000000..dc1170483 --- /dev/null +++ b/docSite/content/zh-cn/docs/development/upgrading/4101.md @@ -0,0 +1,22 @@ +--- +title: 'V4.10.0' +description: 'FastGPT V4.10.0 更新说明' +icon: 'upgrade' +draft: false +toc: true +weight: 784 +--- + + +## 🚀 新增内容 + + +## ⚙️ 优化 + +1. 定时任务报错日志记录到对话日志 + +## 🐛 修复 + +1. 搜索类型系统工具无法正常显示 +2. 部分系统工具向下兼容问题 +3. AI 节点,手动选择历史记录时,会导致 system 记录重复。 \ No newline at end of file diff --git a/packages/service/core/workflow/dispatch/utils.ts b/packages/service/core/workflow/dispatch/utils.ts index d96494d79..ad0558392 100644 --- a/packages/service/core/workflow/dispatch/utils.ts +++ b/packages/service/core/workflow/dispatch/utils.ts @@ -83,16 +83,14 @@ export const filterToolNodeIdByEdges = ({ export const getHistories = (history?: ChatItemType[] | number, histories: ChatItemType[] = []) => { if (!history) return []; + // Select reference history + if (Array.isArray(history)) return history; + // history is number const systemHistoryIndex = histories.findIndex((item) => item.obj !== ChatRoleEnum.System); const systemHistories = histories.slice(0, systemHistoryIndex); const chatHistories = histories.slice(systemHistoryIndex); - - const filterHistories = (() => { - if (typeof history === 'number') return chatHistories.slice(-(history * 2)); - if (Array.isArray(history)) return history; - return []; - })(); + const filterHistories = chatHistories.slice(-(history * 2)); return [...systemHistories, ...filterHistories]; }; diff --git a/projects/app/src/pageComponents/app/detail/Logs/index.tsx b/projects/app/src/pageComponents/app/detail/Logs/index.tsx index 61c84e6ed..c68f3cbce 100644 --- a/projects/app/src/pageComponents/app/detail/Logs/index.tsx +++ b/projects/app/src/pageComponents/app/detail/Logs/index.tsx @@ -120,7 +120,7 @@ const Logs = () => { refreshDeps: [chatSources, logTitle] } ); - console.log(dateRange, 111); + return ( { getScheduleTriggerApp(); } }); + getScheduleTriggerApp(); }; export const startCron = () => { diff --git a/projects/app/src/service/core/app/utils.ts b/projects/app/src/service/core/app/utils.ts index 21185b5ef..d4303fa89 100644 --- a/projects/app/src/service/core/app/utils.ts +++ b/projects/app/src/service/core/app/utils.ts @@ -22,8 +22,11 @@ import { DispatchNodeResponseKeyEnum } from '@fastgpt/global/core/workflow/runti import { type UserChatItemValueItemType } from '@fastgpt/global/core/chat/type'; import { saveChat } from '@fastgpt/service/core/chat/saveChat'; import { getAppLatestVersion } from '@fastgpt/service/core/app/version/controller'; +import { getErrText } from '@fastgpt/global/common/error/utils'; export const getScheduleTriggerApp = async () => { + addLog.info('Schedule trigger app'); + // 1. Find all the app const apps = await retryFn(() => { return MongoApp.find({ @@ -35,25 +38,26 @@ export const getScheduleTriggerApp = async () => { // 2. Run apps await Promise.allSettled( apps.map(async (app) => { - try { - if (!app.scheduledTriggerConfig) return; - // random delay 0 ~ 60s - await delay(Math.floor(Math.random() * 60 * 1000)); - const { timezone, externalProvider } = await getUserChatInfoAndAuthTeamPoints(app.tmbId); + if (!app.scheduledTriggerConfig) return; + const chatId = getNanoid(); + // random delay 0 ~ 60s + await delay(Math.floor(Math.random() * 60 * 1000)); + const { timezone, externalProvider } = await retryFn(() => + getUserChatInfoAndAuthTeamPoints(app.tmbId) + ); - // Get app latest version - const { nodes, edges, chatConfig } = await getAppLatestVersion(app._id, app); - - const chatId = getNanoid(); - const userQuery: UserChatItemValueItemType[] = [ - { - type: ChatItemValueTypeEnum.text, - text: { - content: app.scheduledTriggerConfig?.defaultPrompt - } + // Get app latest version + const { nodes, edges, chatConfig } = await retryFn(() => getAppLatestVersion(app._id, app)); + const userQuery: UserChatItemValueItemType[] = [ + { + type: ChatItemValueTypeEnum.text, + text: { + content: app.scheduledTriggerConfig?.defaultPrompt } - ]; + } + ]; + try { const { flowUsages, assistantResponses, flowResponses, durationSeconds, system_memories } = await retryFn(() => { return dispatchWorkFlow({ @@ -82,6 +86,8 @@ export const getScheduleTriggerApp = async () => { }); }); + const error = flowResponses[flowResponses.length - 1]?.error; + // Save chat await saveChat({ chatId, @@ -106,7 +112,8 @@ export const getScheduleTriggerApp = async () => { memories: system_memories } ], - durationSeconds + durationSeconds, + errorMsg: getErrText(error) }); createChatUsage({ appName: app.name, @@ -116,15 +123,39 @@ export const getScheduleTriggerApp = async () => { source: UsageSourceEnum.cronJob, flowUsages }); - - // update next time - app.scheduledTriggerNextTime = getNextTimeByCronStringAndTimezone( - app.scheduledTriggerConfig - ); - await app.save(); } catch (error) { - addLog.warn('Schedule trigger error', { error }); + addLog.error('Schedule trigger error', error); + + await saveChat({ + chatId, + appId: app._id, + teamId: String(app.teamId), + tmbId: String(app.tmbId), + nodes, + appChatConfig: chatConfig, + variables: {}, + isUpdateUseTime: false, // owner update use time + newTitle: 'Cron Job', + source: ChatSourceEnum.cronJob, + content: [ + { + obj: ChatRoleEnum.Human, + value: userQuery + }, + { + obj: ChatRoleEnum.AI, + value: [], + [DispatchNodeResponseKeyEnum.nodeResponse]: [] + } + ], + durationSeconds: 0, + errorMsg: getErrText(error) + }); } + + // update next time + app.scheduledTriggerNextTime = getNextTimeByCronStringAndTimezone(app.scheduledTriggerConfig); + await app.save().catch(); }) ); }; diff --git a/test/cases/function/packages/service/core/app/workflow/dispatch/utils.test.ts b/test/cases/function/packages/service/core/app/workflow/dispatch/utils.test.ts new file mode 100644 index 000000000..3df27e947 --- /dev/null +++ b/test/cases/function/packages/service/core/app/workflow/dispatch/utils.test.ts @@ -0,0 +1,106 @@ +import { describe, expect, it } from 'vitest'; +import { getHistories } from '@fastgpt/service/core/workflow/dispatch/utils'; +import { ChatItemValueTypeEnum, ChatRoleEnum } from '@fastgpt/global/core/chat/constants'; +import type { ChatItemType } from '@fastgpt/global/core/chat/type'; + +describe('getHistories test', async () => { + const MockHistories: ChatItemType[] = [ + { + obj: ChatRoleEnum.System, + value: [ + { + type: ChatItemValueTypeEnum.text, + text: { + content: '你好' + } + } + ] + }, + { + obj: ChatRoleEnum.Human, + value: [ + { + type: ChatItemValueTypeEnum.text, + text: { + content: '你好' + } + } + ] + }, + { + obj: ChatRoleEnum.AI, + value: [ + { + type: ChatItemValueTypeEnum.text, + text: { + content: '你好2' + } + } + ] + }, + { + obj: ChatRoleEnum.Human, + value: [ + { + type: ChatItemValueTypeEnum.text, + text: { + content: '你好3' + } + } + ] + }, + { + obj: ChatRoleEnum.AI, + value: [ + { + type: ChatItemValueTypeEnum.text, + text: { + content: '你好4' + } + } + ] + } + ]; + + it('getHistories', async () => { + // Number + expect(getHistories(1, MockHistories)).toEqual([ + ...MockHistories.slice(0, 1), + ...MockHistories.slice(-2) + ]); + expect(getHistories(2, MockHistories)).toEqual([...MockHistories.slice(0)]); + expect(getHistories(4, MockHistories)).toEqual([...MockHistories.slice(0)]); + + // Array + expect( + getHistories( + [ + { + obj: ChatRoleEnum.Human, + value: [ + { + type: ChatItemValueTypeEnum.text, + text: { + content: '你好' + } + } + ] + } + ], + MockHistories + ) + ).toEqual([ + { + obj: ChatRoleEnum.Human, + value: [ + { + type: ChatItemValueTypeEnum.text, + text: { + content: '你好' + } + } + ] + } + ]); + }); +});