mirror of
https://github.com/labring/FastGPT.git
synced 2025-10-18 01:16:01 +00:00
4.13.1 features (#5728)
* fix(api): 修复二级路由下的页面判断逻辑 在请求错误处理中,添加基础URL前缀以正确判断当前是否为外部链接页面。 * perf: use global var * remove invalid code * feat: response limit;perf: copy avatar image;perf: markdown parse (#5719) * feat: response limit * remove placeholder * perf: copy avatar image * perf: markdown parse * fix: child app cannot show cite * doc * fix: node template bugs (#5727) * add dataset search count track (#5721) * add dataset search count track * remove pro * change to track * remove unused * fix * perf: track code --------- Co-authored-by: archer <545436317@qq.com> * http response limit * deploy doc * fix: test * doc * remove invalid code * remove invalid code --------- Co-authored-by: 戴盛利 <1639499287@qq.com> Co-authored-by: heheer <heheer@sealos.io>
This commit is contained in:
@@ -83,6 +83,8 @@ USE_IP_LIMIT=false
|
||||
WORKFLOW_MAX_RUN_TIMES=500
|
||||
# 循环最大运行次数,避免极端的死循环情况
|
||||
WORKFLOW_MAX_LOOP_TIMES=50
|
||||
# 服务器接收请求,最大大小,单位 MB
|
||||
SERVICE_REQUEST_MAX_CONTENT_LENGTH=10
|
||||
# 启用内网 IP 检查
|
||||
CHECK_INTERNAL_IP=false
|
||||
# 密码错误锁时长:s
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "app",
|
||||
"version": "4.13.0",
|
||||
"version": "4.13.1",
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"dev": "next dev",
|
||||
|
@@ -14,6 +14,11 @@ export enum CodeClassNameEnum {
|
||||
}
|
||||
|
||||
export const mdTextFormat = (text: string) => {
|
||||
// 处理 Windows 文件路径中的反斜杠,防止被 Markdown 转义:C:\path\file 或 c:\path\file
|
||||
text = text.replace(/([A-Za-z]:\\[^\s`\[\]()]*)/g, (match) => {
|
||||
return match.replace(/\\/g, '\\\\');
|
||||
});
|
||||
|
||||
// NextChat function - Format latex to $$
|
||||
const pattern = /(```[\s\S]*?```|`.*?`)|\\\[([\s\S]*?[^\\])\\\]|\\\((.*?)\\\)/g;
|
||||
text = text.replace(pattern, (match, codeBlock, squareBracket, roundBracket) => {
|
||||
|
@@ -94,7 +94,6 @@ export const FormInputComponent = React.memo(function FormInputComponent({
|
||||
inputType={inputType}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
placeholder={input.label}
|
||||
isDisabled={submitted}
|
||||
isInvalid={!!error}
|
||||
maxLength={input.maxLength}
|
||||
|
@@ -20,7 +20,8 @@ export async function register() {
|
||||
{ preLoadWorker },
|
||||
{ loadSystemModels },
|
||||
{ connectSignoz },
|
||||
{ getSystemTools }
|
||||
{ getSystemTools },
|
||||
{ trackTimerProcess }
|
||||
] = await Promise.all([
|
||||
import('@fastgpt/service/common/mongo/init'),
|
||||
import('@fastgpt/service/common/mongo/index'),
|
||||
@@ -34,7 +35,8 @@ export async function register() {
|
||||
import('@fastgpt/service/worker/preload'),
|
||||
import('@fastgpt/service/core/ai/config/utils'),
|
||||
import('@fastgpt/service/common/otel/trace/register'),
|
||||
import('@fastgpt/service/core/app/plugin/controller')
|
||||
import('@fastgpt/service/core/app/plugin/controller'),
|
||||
import('@fastgpt/service/common/middle/tracks/processor')
|
||||
]);
|
||||
|
||||
// connect to signoz
|
||||
@@ -61,6 +63,7 @@ export async function register() {
|
||||
startMongoWatch();
|
||||
startCron();
|
||||
startTrainingQueue(true);
|
||||
trackTimerProcess();
|
||||
|
||||
console.log('Init system success');
|
||||
}
|
||||
|
@@ -275,6 +275,13 @@ const NodeTemplateList = ({
|
||||
});
|
||||
|
||||
const currentNode = nodeList.find((node) => node.nodeId === handleParams?.nodeId);
|
||||
if (templateNode.flowNodeType === FlowNodeTypeEnum.loop && !!currentNode?.parentNodeId) {
|
||||
toast({
|
||||
status: 'warning',
|
||||
title: t('workflow:can_not_loop')
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const newNode = nodeTemplate2FlowNode({
|
||||
template: {
|
||||
|
@@ -166,6 +166,7 @@ const InputFormEditModal = ({
|
||||
}}
|
||||
onClick={() => {
|
||||
setValue('type', item.value);
|
||||
setValue('defaultValue', '');
|
||||
}}
|
||||
>
|
||||
<MyIcon
|
||||
|
@@ -296,6 +296,7 @@ const FieldEditModal = ({
|
||||
}}
|
||||
onClick={() => {
|
||||
setValue('renderTypeList', item.value);
|
||||
setValue('defaultValue', '');
|
||||
}}
|
||||
>
|
||||
<MyIcon
|
||||
|
@@ -8,6 +8,8 @@ import { onCreateApp } from './create';
|
||||
import { AuditEventEnum } from '@fastgpt/global/support/user/audit/constants';
|
||||
import { addAuditLog } from '@fastgpt/service/support/user/audit/util';
|
||||
import { getI18nAppType } from '@fastgpt/service/support/user/audit/util';
|
||||
import { copyImage } from '@fastgpt/service/common/file/image/controller';
|
||||
import { mongoSessionRun } from '@fastgpt/service/common/mongo/sessionRun';
|
||||
|
||||
export type copyAppQuery = {};
|
||||
|
||||
@@ -32,19 +34,32 @@ async function handler(
|
||||
? await authApp({ req, appId: app.parentId, per: WritePermissionVal, authToken: true })
|
||||
: await authUserPer({ req, authToken: true, per: TeamAppCreatePermissionVal });
|
||||
|
||||
const appId = await onCreateApp({
|
||||
parentId: app.parentId,
|
||||
name: app.name + ' Copy',
|
||||
intro: app.intro,
|
||||
avatar: app.avatar,
|
||||
type: app.type,
|
||||
modules: app.modules,
|
||||
edges: app.edges,
|
||||
chatConfig: app.chatConfig,
|
||||
teamId: app.teamId,
|
||||
tmbId,
|
||||
pluginData: app.pluginData
|
||||
// Copy avatar
|
||||
const { appId } = await mongoSessionRun(async (session) => {
|
||||
const avatar = await copyImage({
|
||||
teamId,
|
||||
imageUrl: app.avatar,
|
||||
session
|
||||
});
|
||||
|
||||
const appId = await onCreateApp({
|
||||
parentId: app.parentId,
|
||||
name: app.name + ' Copy',
|
||||
intro: app.intro,
|
||||
avatar,
|
||||
type: app.type,
|
||||
modules: app.modules,
|
||||
edges: app.edges,
|
||||
chatConfig: app.chatConfig,
|
||||
teamId: app.teamId,
|
||||
tmbId,
|
||||
pluginData: app.pluginData,
|
||||
session
|
||||
});
|
||||
|
||||
return { appId };
|
||||
});
|
||||
|
||||
(async () => {
|
||||
addAuditLog({
|
||||
tmbId,
|
||||
|
@@ -47,7 +47,7 @@ async function handler(req: ApiRequestProps<SearchTestProps>): Promise<SearchTes
|
||||
const start = Date.now();
|
||||
|
||||
// auth dataset role
|
||||
const { dataset, teamId, tmbId, apikey } = await authDataset({
|
||||
const { dataset, teamId, tmbId, userId, apikey } = await authDataset({
|
||||
req,
|
||||
authToken: true,
|
||||
authApiKey: true,
|
||||
|
@@ -8,7 +8,7 @@ import { clearToken } from '@/web/support/user/auth';
|
||||
import { TOKEN_ERROR_CODE } from '@fastgpt/global/common/error/errorCode';
|
||||
import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';
|
||||
import { useSystemStore } from '../system/useSystemStore';
|
||||
import { getWebReqUrl } from '@fastgpt/web/common/system/utils';
|
||||
import { getWebReqUrl, subRoute } from '@fastgpt/web/common/system/utils';
|
||||
import { i18nT } from '@fastgpt/web/i18n/utils';
|
||||
import { getNanoid } from '@fastgpt/global/common/string/tools';
|
||||
|
||||
@@ -110,9 +110,9 @@ function checkRes(data: ResponseDataType) {
|
||||
function responseError(err: any) {
|
||||
console.log('error->', '请求错误', err);
|
||||
const isOutlinkPage = {
|
||||
'/chat/share': true,
|
||||
'/chat': true,
|
||||
'/login': true
|
||||
[`${subRoute}/chat/share`]: true,
|
||||
[`${subRoute}/chat`]: true,
|
||||
[`${subRoute}/login`]: true
|
||||
}[window.location.pathname];
|
||||
|
||||
const data = err?.response?.data || err;
|
||||
|
@@ -87,7 +87,9 @@ export const storeNode2FlowNode = ({
|
||||
moduleTemplatesFlat.find((template) => template.flowNodeType === storeNode.flowNodeType) ||
|
||||
EmptyNode;
|
||||
|
||||
const templateInputs = template.inputs.filter((input) => !input.canEdit);
|
||||
const templateInputs = template.inputs.filter(
|
||||
(input) => !input.canEdit && input.deprecated !== true
|
||||
);
|
||||
const templateOutputs = template.outputs.filter(
|
||||
(output) => output.type !== FlowNodeOutputTypeEnum.dynamic
|
||||
);
|
||||
|
@@ -75,7 +75,7 @@ describe('storeNode2FlowNode with deprecated inputs/outputs', () => {
|
||||
|
||||
const deprecatedInput = result.data.inputs.find((input) => input.key === 'deprecatedInput');
|
||||
expect(deprecatedInput).toBeDefined();
|
||||
expect(deprecatedInput?.deprecated).toBe(true);
|
||||
expect(deprecatedInput?.deprecated).toBe(undefined);
|
||||
|
||||
const deprecatedOutput = result.data.outputs.find(
|
||||
(output) => output.key === 'deprecatedOutput'
|
||||
|
@@ -9,8 +9,26 @@ import {
|
||||
import { TeamErrEnum } from '@fastgpt/global/common/error/code/team';
|
||||
import { TOKEN_ERROR_CODE } from '@fastgpt/global/common/error/errorCode';
|
||||
|
||||
// Mock all required dependencies
|
||||
vi.mock('@fastgpt/web/common/system/utils', () => ({
|
||||
getWebReqUrl: vi.fn().mockReturnValue('http://test.com')
|
||||
getWebReqUrl: vi.fn().mockReturnValue('http://test.com'),
|
||||
subRoute: '/test-route' // Add subRoute mock
|
||||
}));
|
||||
|
||||
vi.mock('@/web/support/user/auth', () => ({
|
||||
clearToken: vi.fn()
|
||||
}));
|
||||
|
||||
vi.mock('../system/useSystemStore', () => ({
|
||||
useSystemStore: {
|
||||
getState: vi.fn().mockReturnValue({
|
||||
setNotSufficientModalType: vi.fn()
|
||||
})
|
||||
}
|
||||
}));
|
||||
|
||||
vi.mock('@fastgpt/web/i18n/utils', () => ({
|
||||
i18nT: vi.fn().mockReturnValue('Unauthorized token')
|
||||
}));
|
||||
|
||||
// Mock window.location
|
||||
@@ -99,7 +117,7 @@ describe('request utils', () => {
|
||||
});
|
||||
|
||||
it('should handle token error for outlink page', async () => {
|
||||
mockLocation.pathname = '/chat/share';
|
||||
mockLocation.pathname = '/test-route/chat/share';
|
||||
const err = {
|
||||
response: {
|
||||
data: {
|
||||
|
Reference in New Issue
Block a user