= ({
nodeId={nodeId}
varName={varName}
formInput={payload}
+ unavailableVariableNames={unavailableVariableNames}
onChange={handleChange}
onRename={onRename}
onRemove={onRemove}
diff --git a/web/app/components/base/prompt-editor/plugins/hitl-input-block/input-field.tsx b/web/app/components/base/prompt-editor/plugins/hitl-input-block/input-field.tsx
index 2938dd082c..5a8b3fa927 100644
--- a/web/app/components/base/prompt-editor/plugins/hitl-input-block/input-field.tsx
+++ b/web/app/components/base/prompt-editor/plugins/hitl-input-block/input-field.tsx
@@ -31,6 +31,7 @@ type InputFieldProps = {
nodeId: string
isEdit: boolean
payload?: FormInputItem
+ unavailableVariableNames?: string[]
onChange: (newPayload: FormInputItem) => void
onCancel: () => void
}
@@ -38,6 +39,7 @@ const InputField: React.FC
= ({
nodeId,
isEdit,
payload,
+ unavailableVariableNames = [],
onChange,
onCancel,
}) => {
@@ -73,14 +75,24 @@ const InputField: React.FC = ({
return createDefaultParagraphFormInput(tempPayload.output_variable_name)
}, [tempPayload])
- const nameValid = useMemo(() => {
+ const unavailableVariableNameSet = useMemo(() => {
+ return new Set(unavailableVariableNames.map(name => name.trim()).filter(Boolean))
+ }, [unavailableVariableNames])
+ const variableNameError = useMemo(() => {
const name = tempPayload.output_variable_name.trim()
if (!name)
- return false
+ return null
if (name.includes(' '))
- return false
- return /^[a-z_]\w{0,29}$/.test(name)
- }, [tempPayload.output_variable_name])
+ return 'variableNameInvalid'
+ if (!/^[a-z_]\w{0,29}$/.test(name))
+ return 'variableNameInvalid'
+ if (unavailableVariableNameSet.has(name))
+ return 'variableNameDuplicated'
+ return null
+ }, [tempPayload.output_variable_name, unavailableVariableNameSet])
+ const nameValid = useMemo(() => {
+ return !!tempPayload.output_variable_name.trim() && !variableNameError
+ }, [tempPayload.output_variable_name, variableNameError])
const handleSave = useCallback(() => {
if (!nameValid)
return
@@ -223,9 +235,9 @@ const InputField: React.FC = ({
}}
autoFocus
/>
- {tempPayload.output_variable_name && !nameValid && (
+ {tempPayload.output_variable_name && variableNameError && (
- {t(`${i18nPrefix}.variableNameInvalid`, { ns: 'workflow' })}
+ {t(`${i18nPrefix}.${variableNameError}`, { ns: 'workflow' })}
)}
diff --git a/web/app/components/workflow/nodes/human-input/components/__tests__/form-content.spec.tsx b/web/app/components/workflow/nodes/human-input/components/__tests__/form-content.spec.tsx
index 218da57fbb..9c1912d71b 100644
--- a/web/app/components/workflow/nodes/human-input/components/__tests__/form-content.spec.tsx
+++ b/web/app/components/workflow/nodes/human-input/components/__tests__/form-content.spec.tsx
@@ -64,6 +64,7 @@ vi.mock('@/app/components/base/prompt-editor', () => ({
vi.mock('../add-input-field', () => ({
__esModule: true,
default: (props: {
+ unavailableVariableNames?: string[]
onSave: (payload: {
type: string
output_variable_name: string
@@ -231,6 +232,41 @@ describe('FormContent', () => {
expect(container.firstChild).toHaveClass('pointer-events-none')
})
+ it('should not insert a new input when the variable name already exists', () => {
+ render(
+