feat: enhance human input panel with structured output and variable handling improvements

This commit is contained in:
twwu 2025-12-25 14:53:19 +08:00
parent 8b9846f52b
commit 8b65b689f7
5 changed files with 40 additions and 12 deletions

View File

@ -1,10 +1,11 @@
'use client'
import type { FC } from 'react'
import type { ValueSelector } from '@/app/components/workflow/types'
import type { ValueSelector, Var } from '@/app/components/workflow/types'
import * as React from 'react'
import { useCallback, useState } from 'react'
import { Trans, useTranslation } from 'react-i18next'
import VarReferencePicker from '@/app/components/workflow/nodes/_base/components/variable/var-reference-picker'
import { VarType } from '@/app/components/workflow/types'
import { cn } from '@/utils/classnames'
import Textarea from '../../../textarea'
import TagLabel from './tag-label'
@ -76,6 +77,9 @@ const PrePopulate: FC<Props> = ({
onChange: onValueSelectorChange!,
readonly: false,
zIndex: 1000000, // bigger than shortcut plugin popup
filterVar: (varPayload: Var) => {
return [VarType.string, VarType.number, VarType.secret].includes(varPayload.type)
},
}
const isShowPlaceholder = !onPlaceholderClicked && (isVariable ? (!valueSelector || valueSelector.length === 0) : !value)

View File

@ -2,6 +2,7 @@
import type { LexicalCommand } from 'lexical'
import type { FC } from 'react'
import type { FormInputItem } from '../types'
import type { Node, NodeOutPutVar } from '@/app/components/workflow/types'
import { useBoolean } from 'ahooks'
import * as React from 'react'
import { useEffect, useState } from 'react'
@ -12,7 +13,6 @@ import { cn } from '@/utils/classnames'
import { useWorkflowVariableType } from '../../../hooks'
import { BlockEnum } from '../../../types'
import { isMac } from '../../../utils'
import useAvailableVarList from '../../_base/hooks/use-available-var-list'
import AddInputField from './add-input-field'
type FormContentProps = {
@ -25,6 +25,8 @@ type FormContentProps = {
onFormInputItemRemove: (varName: string) => void
editorKey: number
isExpand: boolean
availableVars: NodeOutPutVar[]
availableNodes: Node[]
}
const Key: FC<{ children: React.ReactNode, className?: string }> = ({ children, className }) => {
@ -45,16 +47,10 @@ const FormContent: FC<FormContentProps> = ({
onFormInputItemRemove,
editorKey,
isExpand,
availableVars,
availableNodes,
}) => {
const { t } = useTranslation()
const filterVar = () => true
const {
availableVars,
availableNodesWithParent: availableNodes,
} = useAvailableVarList(nodeId, {
onlyLeafNodeVar: false,
filterVar,
})
const getVarType = useWorkflowVariableType()

View File

@ -17,6 +17,8 @@ import Button from '@/app/components/base/button'
import Divider from '@/app/components/base/divider'
import Toast from '@/app/components/base/toast'
import Tooltip from '@/app/components/base/tooltip'
import OutputVars, { VarItem } from '@/app/components/workflow/nodes/_base/components/output-vars'
import Split from '@/app/components/workflow/nodes/_base/components/split'
import useAvailableVarList from '@/app/components/workflow/nodes/_base/hooks/use-available-var-list'
import { useStore } from '@/app/components/workflow/store'
import { VarType } from '@/app/components/workflow/types'
@ -49,6 +51,8 @@ const Panel: FC<NodePanelProps<HumanInputNodeType>> = ({
handleFormInputItemRename,
handleFormInputItemRemove,
editorKey,
structuredOutputCollapsed,
setStructuredOutputCollapsed,
} = useConfig(id, data)
const { availableVars, availableNodesWithParent } = useAvailableVarList(id, {
@ -122,6 +126,8 @@ const Panel: FC<NodePanelProps<HumanInputNodeType>> = ({
onFormInputItemRename={handleFormInputItemRename}
onFormInputItemRemove={handleFormInputItemRemove}
isExpand={isExpandFormContent}
availableVars={availableVars}
availableNodes={availableNodesWithParent}
/>
</div>
{/* user actions */}
@ -154,7 +160,7 @@ const Panel: FC<NodePanelProps<HumanInputNodeType>> = ({
<div className="space-y-2">
{inputs.user_actions.map((action, index) => (
<UserActionItem
key={index}
key={action.id}
data={action}
onChange={data => handleUserActionChange(index, data)}
onDelete={handleUserActionDelete}
@ -175,6 +181,23 @@ const Panel: FC<NodePanelProps<HumanInputNodeType>> = ({
onChange={handleTimeoutChange}
/>
</div>
{/* output vars */}
<Split />
<OutputVars
collapsed={structuredOutputCollapsed}
onCollapse={setStructuredOutputCollapsed}
>
{
inputs.inputs.map(input => (
<VarItem
key={input.output_variable_name}
name={input.output_variable_name}
type={VarType.string}
description="Form input value"
/>
))
}
</OutputVars>
{isPreview && (
<FormContentPreview

View File

@ -1,5 +1,6 @@
import type { DeliveryMethod, HumanInputNodeType, UserAction } from './types'
import { produce } from 'immer'
import { useState } from 'react'
import {
useNodesReadOnly,
} from '@/app/components/workflow/hooks'
@ -10,6 +11,7 @@ const useConfig = (id: string, payload: HumanInputNodeType) => {
const { nodesReadOnly: readOnly } = useNodesReadOnly()
const { inputs, setInputs } = useNodeCrud<HumanInputNodeType>(id, payload)
const formContentHook = useFormContent(id, payload)
const [structuredOutputCollapsed, setStructuredOutputCollapsed] = useState(true)
const handleDeliveryMethodChange = (methods: DeliveryMethod[]) => {
setInputs({
@ -60,6 +62,8 @@ const useConfig = (id: string, payload: HumanInputNodeType) => {
handleUserActionChange,
handleUserActionDelete,
handleTimeoutChange,
structuredOutputCollapsed,
setStructuredOutputCollapsed,
...formContentHook,
}
}

View File

@ -94,7 +94,8 @@ const Panel: FC<NodePanelProps<LLMNodeType>> = ({
handleModelChanged(model)
}
})()
}, [inputs.model.completion_params])
}, [handleCompletionParamsChange, handleModelChanged, inputs.model.completion_params, t])
return (
<div className="mt-2">
<div className="space-y-4 px-4 pb-4">