diff --git a/packages/global/core/workflow/runtime/utils.ts b/packages/global/core/workflow/runtime/utils.ts index 8fef7e728..a226ff7f1 100644 --- a/packages/global/core/workflow/runtime/utils.ts +++ b/packages/global/core/workflow/runtime/utils.ts @@ -67,25 +67,8 @@ export const valueTypeFormat = (value: any, valueType?: WorkflowIOValueTypeEnum) }; // Handle null/undefined, return default value by type - if (value === undefined || value === null) { - if (!valueType || valueType === WorkflowIOValueTypeEnum.any) return value; - - // Default value map (use function to ensure new reference each time) - const defaultValueMap: Partial any>> = { - [WorkflowIOValueTypeEnum.string]: () => '', - [WorkflowIOValueTypeEnum.number]: () => 0, - [WorkflowIOValueTypeEnum.boolean]: () => false, - [WorkflowIOValueTypeEnum.arrayString]: () => [], - [WorkflowIOValueTypeEnum.arrayNumber]: () => [], - [WorkflowIOValueTypeEnum.arrayBoolean]: () => [], - [WorkflowIOValueTypeEnum.arrayObject]: () => [], - [WorkflowIOValueTypeEnum.arrayAny]: () => [], - [WorkflowIOValueTypeEnum.object]: () => ({}) - }; - - const getDefaultValue = defaultValueMap[valueType]; - return getDefaultValue ? getDefaultValue() : value; - } + if (value === undefined || value === null) return value; + if (!valueType || valueType === WorkflowIOValueTypeEnum.any) return value; // Password check if (valueType === WorkflowIOValueTypeEnum.string && isSecretValue(value)) return value; diff --git a/packages/service/core/ai/llm/request.ts b/packages/service/core/ai/llm/request.ts index e8983aba5..d9b317a5e 100644 --- a/packages/service/core/ai/llm/request.ts +++ b/packages/service/core/ai/llm/request.ts @@ -537,7 +537,7 @@ const llmCompletionsBodyFormat = async ({ : undefined, ...modelData?.defaultConfig, response_format, - stop: stop?.split('|'), + stop: stop?.split('|').filter((item) => !!item.trim()), ...(toolCallMode === 'toolChoice' && { tools, tool_choice, diff --git a/packages/service/core/ai/utils.ts b/packages/service/core/ai/utils.ts index 83287ddc0..5df84546c 100644 --- a/packages/service/core/ai/utils.ts +++ b/packages/service/core/ai/utils.ts @@ -20,7 +20,7 @@ export const computedMaxToken = ({ if (maxToken === undefined) return; maxToken = Math.min(maxToken, model.maxResponse); - return Math.max(maxToken, min || 0); + return Math.max(maxToken, min || 1); }; // FastGPT temperature range: [0,10], ai temperature:[0,2],{0,1]…… diff --git a/packages/service/core/workflow/dispatch/tools/http468.ts b/packages/service/core/workflow/dispatch/tools/http468.ts index a92918a2f..d39c4844a 100644 --- a/packages/service/core/workflow/dispatch/tools/http468.ts +++ b/packages/service/core/workflow/dispatch/tools/http468.ts @@ -62,14 +62,13 @@ const UNDEFINED_SIGN = 'UNDEFINED_SIGN'; export const dispatchHttp468Request = async (props: HttpRequestProps): Promise => { let { - runningAppInfo: { id: appId, teamId, tmbId }, + runningAppInfo: { id: appId }, chatId, responseChatItemId, variables, node, runtimeNodes, histories, - workflowStreamResponse, params: { system_httpMethod: httpMethod = 'POST', system_httpReqUrl: httpReqUrl, @@ -332,8 +331,10 @@ export const replaceJsonBodyString = ( }; const valToStr = (val: any, isQuoted = false) => { - if (val === undefined) return 'null'; - if (val === null) return 'null'; + if (val === undefined || val === null) { + if (isQuoted) return ''; + return 'null'; + } if (typeof val === 'object') { const jsonStr = JSON.stringify(val); diff --git a/test/cases/service/core/app/workflow/dispatch/http.test.ts b/test/cases/service/core/app/workflow/dispatch/http.test.ts index c92e2fc94..76b2ddf1b 100644 --- a/test/cases/service/core/app/workflow/dispatch/http.test.ts +++ b/test/cases/service/core/app/workflow/dispatch/http.test.ts @@ -19,6 +19,8 @@ describe('replaceJsonBodyString', () => { ] as unknown as RuntimeNodeItemType[]; const mockVariables = { + undefinedVar: undefined, + nullVar: null, userName: 'John Doe', userAge: 30, isActive: true, @@ -43,6 +45,14 @@ describe('replaceJsonBodyString', () => { }; describe('Basic variable replacement functionality', () => { + it('字符串为空', () => { + const input = '{"name": "{{undefinedVar}}"}'; + const expected = '{"name": ""}'; + + const result = replaceJsonBodyString({ text: input }, mockProps); + expect(result).toBe(expected); + }); + it('should correctly replace string variables', () => { const input = '{"name": "{{userName}}", "greeting": "Hello {{userName}}"}'; const expected = '{"name": "John Doe", "greeting": "Hello John Doe"}'; @@ -241,7 +251,7 @@ describe('replaceJsonBodyString', () => { it('should handle non-existent variables', () => { const input = '{"missing": "{{nonExistentVar}}", "static": "value"}'; - const expected = '{"missing": "null", "static": "value"}'; + const expected = '{"missing": "", "static": "value"}'; const result = replaceJsonBodyString({ text: input }, mockProps); expect(result).toBe(expected); @@ -626,7 +636,7 @@ describe('replaceJsonBodyString', () => { // Verify no code execution occurred (template injection variable was replaced with null because it doesn't exist) expect(typeof parsed.templateTests.inject).toBe('string'); - expect(parsed.templateTests.inject).toBe('null'); // Non-existent variables become "null" + expect(parsed.templateTests.inject).toBe(''); // Non-existent variables become "null" }); }); }); diff --git a/test/cases/service/core/app/workflow/dispatch/utils.test.ts b/test/cases/service/core/app/workflow/dispatch/utils.test.ts index 66e6ccb96..100fa4008 100644 --- a/test/cases/service/core/app/workflow/dispatch/utils.test.ts +++ b/test/cases/service/core/app/workflow/dispatch/utils.test.ts @@ -311,109 +311,3 @@ describe('valueTypeFormat', () => { // }); // }); }); - -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: '你好' - } - } - ] - } - ]); - }); -});