From c086aa107cce8d073b287083a31af0f53ae1f644 Mon Sep 17 00:00:00 2001 From: crazywoola <100913391+crazywoola@users.noreply.github.com> Date: Thu, 18 Dec 2025 11:21:12 +0800 Subject: [PATCH] fix: TypeError: outputParameters is not iterable (#29833) --- .../components/tools/workflow-tool/index.tsx | 5 +- .../tools/workflow-tool/utils.test.ts | 47 +++++++++++++++++++ .../components/tools/workflow-tool/utils.ts | 28 +++++++++++ 3 files changed, 79 insertions(+), 1 deletion(-) create mode 100644 web/app/components/tools/workflow-tool/utils.test.ts create mode 100644 web/app/components/tools/workflow-tool/utils.ts diff --git a/web/app/components/tools/workflow-tool/index.tsx b/web/app/components/tools/workflow-tool/index.tsx index 7ce5acb228..8af7fb4c9f 100644 --- a/web/app/components/tools/workflow-tool/index.tsx +++ b/web/app/components/tools/workflow-tool/index.tsx @@ -4,6 +4,7 @@ import React, { useMemo, useState } from 'react' import { useTranslation } from 'react-i18next' import { produce } from 'immer' import type { Emoji, WorkflowToolProviderOutputParameter, WorkflowToolProviderParameter, WorkflowToolProviderRequest } from '../types' +import { buildWorkflowOutputParameters } from './utils' import cn from '@/utils/classnames' import Drawer from '@/app/components/base/drawer-plus' import Input from '@/app/components/base/input' @@ -47,7 +48,9 @@ const WorkflowToolAsModal: FC = ({ const [name, setName] = useState(payload.name) const [description, setDescription] = useState(payload.description) const [parameters, setParameters] = useState(payload.parameters) - const outputParameters = useMemo(() => payload.outputParameters, [payload.outputParameters]) + const rawOutputParameters = payload.outputParameters + const outputSchema = payload.tool?.output_schema + const outputParameters = useMemo(() => buildWorkflowOutputParameters(rawOutputParameters, outputSchema), [rawOutputParameters, outputSchema]) const reservedOutputParameters: WorkflowToolProviderOutputParameter[] = [ { name: 'text', diff --git a/web/app/components/tools/workflow-tool/utils.test.ts b/web/app/components/tools/workflow-tool/utils.test.ts new file mode 100644 index 0000000000..fef8c05489 --- /dev/null +++ b/web/app/components/tools/workflow-tool/utils.test.ts @@ -0,0 +1,47 @@ +import { VarType } from '@/app/components/workflow/types' +import type { WorkflowToolProviderOutputParameter, WorkflowToolProviderOutputSchema } from '../types' +import { buildWorkflowOutputParameters } from './utils' + +describe('buildWorkflowOutputParameters', () => { + it('returns provided output parameters when array input exists', () => { + const params: WorkflowToolProviderOutputParameter[] = [ + { name: 'text', description: 'final text', type: VarType.string }, + ] + + const result = buildWorkflowOutputParameters(params, null) + + expect(result).toBe(params) + }) + + it('derives parameters from schema when explicit array missing', () => { + const schema: WorkflowToolProviderOutputSchema = { + type: 'object', + properties: { + answer: { + type: VarType.string, + description: 'AI answer', + }, + attachments: { + type: VarType.arrayFile, + description: 'Supporting files', + }, + unknown: { + type: 'custom', + description: 'Unsupported type', + }, + }, + } + + const result = buildWorkflowOutputParameters(undefined, schema) + + expect(result).toEqual([ + { name: 'answer', description: 'AI answer', type: VarType.string }, + { name: 'attachments', description: 'Supporting files', type: VarType.arrayFile }, + { name: 'unknown', description: 'Unsupported type', type: undefined }, + ]) + }) + + it('returns empty array when no source information is provided', () => { + expect(buildWorkflowOutputParameters(null, null)).toEqual([]) + }) +}) diff --git a/web/app/components/tools/workflow-tool/utils.ts b/web/app/components/tools/workflow-tool/utils.ts new file mode 100644 index 0000000000..80d832fb47 --- /dev/null +++ b/web/app/components/tools/workflow-tool/utils.ts @@ -0,0 +1,28 @@ +import type { WorkflowToolProviderOutputParameter, WorkflowToolProviderOutputSchema } from '../types' +import { VarType } from '@/app/components/workflow/types' + +const validVarTypes = new Set(Object.values(VarType)) + +const normalizeVarType = (type?: string): VarType | undefined => { + if (!type) + return undefined + + return validVarTypes.has(type) ? type as VarType : undefined +} + +export const buildWorkflowOutputParameters = ( + outputParameters: WorkflowToolProviderOutputParameter[] | null | undefined, + outputSchema?: WorkflowToolProviderOutputSchema | null, +): WorkflowToolProviderOutputParameter[] => { + if (Array.isArray(outputParameters)) + return outputParameters + + if (!outputSchema?.properties) + return [] + + return Object.entries(outputSchema.properties).map(([name, schema]) => ({ + name, + description: schema.description, + type: normalizeVarType(schema.type), + })) +}