mirror of
https://github.com/langgenius/dify.git
synced 2026-04-29 12:37:20 +08:00
feat: custom credential form
This commit is contained in:
parent
e0b7f48b6b
commit
b7e56a23a0
@ -1,5 +1,5 @@
|
|||||||
import { useCallback, useState } from 'react'
|
import { useCallback, useState } from 'react'
|
||||||
import type { FC } from 'react'
|
import type { ReactNode } from 'react'
|
||||||
import { ValidatingTip } from '../../key-validator/ValidateStatus'
|
import { ValidatingTip } from '../../key-validator/ValidateStatus'
|
||||||
import type {
|
import type {
|
||||||
CredentialFormSchema,
|
CredentialFormSchema,
|
||||||
@ -22,13 +22,15 @@ import ToolSelector from '@/app/components/plugins/plugin-detail-panel/tool-sele
|
|||||||
import AppSelector from '@/app/components/plugins/plugin-detail-panel/app-selector'
|
import AppSelector from '@/app/components/plugins/plugin-detail-panel/app-selector'
|
||||||
import RadioE from '@/app/components/base/radio/ui'
|
import RadioE from '@/app/components/base/radio/ui'
|
||||||
|
|
||||||
type FormProps = {
|
type FormProps<
|
||||||
|
CustomFormSchema extends Omit<CredentialFormSchema, 'type'> & { type: string } = never,
|
||||||
|
> = {
|
||||||
className?: string
|
className?: string
|
||||||
itemClassName?: string
|
itemClassName?: string
|
||||||
fieldLabelClassName?: string
|
fieldLabelClassName?: string
|
||||||
value: FormValue
|
value: FormValue
|
||||||
onChange: (val: FormValue) => void
|
onChange: (val: FormValue) => void
|
||||||
formSchemas: CredentialFormSchema[]
|
formSchemas: Array<CredentialFormSchema | CustomFormSchema>
|
||||||
validating: boolean
|
validating: boolean
|
||||||
validatedSuccess?: boolean
|
validatedSuccess?: boolean
|
||||||
showOnVariableMap: Record<string, string[]>
|
showOnVariableMap: Record<string, string[]>
|
||||||
@ -36,10 +38,13 @@ type FormProps = {
|
|||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
inputClassName?: string
|
inputClassName?: string
|
||||||
isShowDefaultValue?: boolean
|
isShowDefaultValue?: boolean
|
||||||
fieldMoreInfo?: (payload: CredentialFormSchema) => JSX.Element | null
|
fieldMoreInfo?: (payload: CredentialFormSchema | CustomFormSchema) => ReactNode
|
||||||
|
customRenderField?: (formSchema: CustomFormSchema, props: FormProps<CustomFormSchema>) => ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
const Form: FC<FormProps> = ({
|
function Form<
|
||||||
|
CustomFormSchema extends Omit<CredentialFormSchema, 'type'> & { type: string } = never,
|
||||||
|
>({
|
||||||
className,
|
className,
|
||||||
itemClassName,
|
itemClassName,
|
||||||
fieldLabelClassName,
|
fieldLabelClassName,
|
||||||
@ -54,7 +59,8 @@ const Form: FC<FormProps> = ({
|
|||||||
inputClassName,
|
inputClassName,
|
||||||
isShowDefaultValue = false,
|
isShowDefaultValue = false,
|
||||||
fieldMoreInfo,
|
fieldMoreInfo,
|
||||||
}) => {
|
customRenderField,
|
||||||
|
}: FormProps<CustomFormSchema>) {
|
||||||
const language = useLanguage()
|
const language = useLanguage()
|
||||||
const [changeKey, setChangeKey] = useState('')
|
const [changeKey, setChangeKey] = useState('')
|
||||||
|
|
||||||
@ -81,25 +87,19 @@ const Form: FC<FormProps> = ({
|
|||||||
onChange({ ...value, [key]: newValue })
|
onChange({ ...value, [key]: newValue })
|
||||||
}, [onChange, value])
|
}, [onChange, value])
|
||||||
|
|
||||||
const renderField = (formSchema: CredentialFormSchema) => {
|
const renderField = (formSchema: CredentialFormSchema | CustomFormSchema) => {
|
||||||
const tooltip = formSchema.tooltip
|
const tooltip = formSchema.tooltip
|
||||||
const tooltipContent = (tooltip && (
|
const tooltipContent = (tooltip && (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
popupContent={
|
popupContent={<div className='w-[200px]'>
|
||||||
<div className='w-[200px]'>
|
{tooltip[language] || tooltip.en_US}
|
||||||
{tooltip[language] || tooltip.en_US}
|
</div>}
|
||||||
</div>}
|
|
||||||
triggerClassName='ml-1 w-4 h-4'
|
triggerClassName='ml-1 w-4 h-4'
|
||||||
asChild={false}
|
asChild={false} />
|
||||||
/>
|
|
||||||
))
|
))
|
||||||
if (formSchema.type === FormTypeEnum.textInput || formSchema.type === FormTypeEnum.secretInput || formSchema.type === FormTypeEnum.textNumber) {
|
if (formSchema.type === FormTypeEnum.textInput || formSchema.type === FormTypeEnum.secretInput || formSchema.type === FormTypeEnum.textNumber) {
|
||||||
const {
|
const {
|
||||||
variable,
|
variable, label, placeholder, required, show_on,
|
||||||
label,
|
|
||||||
placeholder,
|
|
||||||
required,
|
|
||||||
show_on,
|
|
||||||
} = formSchema as (CredentialFormSchemaTextInput | CredentialFormSchemaSecretInput)
|
} = formSchema as (CredentialFormSchemaTextInput | CredentialFormSchemaSecretInput)
|
||||||
|
|
||||||
if (show_on.length && !show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value))
|
if (show_on.length && !show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value))
|
||||||
@ -110,11 +110,9 @@ const Form: FC<FormProps> = ({
|
|||||||
<div key={variable} className={cn(itemClassName, 'py-3')}>
|
<div key={variable} className={cn(itemClassName, 'py-3')}>
|
||||||
<div className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-semibold text-text-secondary')}>
|
<div className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-semibold text-text-secondary')}>
|
||||||
{label[language] || label.en_US}
|
{label[language] || label.en_US}
|
||||||
{
|
{required && (
|
||||||
required && (
|
<span className='ml-1 text-red-500'>*</span>
|
||||||
<span className='ml-1 text-red-500'>*</span>
|
)}
|
||||||
)
|
|
||||||
}
|
|
||||||
{tooltipContent}
|
{tooltipContent}
|
||||||
</div>
|
</div>
|
||||||
<Input
|
<Input
|
||||||
@ -125,8 +123,7 @@ const Form: FC<FormProps> = ({
|
|||||||
placeholder={placeholder?.[language] || placeholder?.en_US}
|
placeholder={placeholder?.[language] || placeholder?.en_US}
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
type={formSchema.type === FormTypeEnum.textNumber ? 'number' : 'text'}
|
type={formSchema.type === FormTypeEnum.textNumber ? 'number' : 'text'}
|
||||||
{...(formSchema.type === FormTypeEnum.textNumber ? { min: (formSchema as CredentialFormSchemaNumberInput).min, max: (formSchema as CredentialFormSchemaNumberInput).max } : {})}
|
{...(formSchema.type === FormTypeEnum.textNumber ? { min: (formSchema as CredentialFormSchemaNumberInput).min, max: (formSchema as CredentialFormSchemaNumberInput).max } : {})} />
|
||||||
/>
|
|
||||||
{fieldMoreInfo?.(formSchema)}
|
{fieldMoreInfo?.(formSchema)}
|
||||||
{validating && changeKey === variable && <ValidatingTip />}
|
{validating && changeKey === variable && <ValidatingTip />}
|
||||||
</div>
|
</div>
|
||||||
@ -135,11 +132,7 @@ const Form: FC<FormProps> = ({
|
|||||||
|
|
||||||
if (formSchema.type === FormTypeEnum.radio) {
|
if (formSchema.type === FormTypeEnum.radio) {
|
||||||
const {
|
const {
|
||||||
options,
|
options, variable, label, show_on, required,
|
||||||
variable,
|
|
||||||
label,
|
|
||||||
show_on,
|
|
||||||
required,
|
|
||||||
} = formSchema as CredentialFormSchemaRadio
|
} = formSchema as CredentialFormSchemaRadio
|
||||||
|
|
||||||
if (show_on.length && !show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value))
|
if (show_on.length && !show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value))
|
||||||
@ -151,36 +144,32 @@ const Form: FC<FormProps> = ({
|
|||||||
<div key={variable} className={cn(itemClassName, 'py-3')}>
|
<div key={variable} className={cn(itemClassName, 'py-3')}>
|
||||||
<div className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-semibold text-text-secondary')}>
|
<div className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-semibold text-text-secondary')}>
|
||||||
{label[language] || label.en_US}
|
{label[language] || label.en_US}
|
||||||
{
|
{required && (
|
||||||
required && (
|
<span className='ml-1 text-red-500'>*</span>
|
||||||
<span className='ml-1 text-red-500'>*</span>
|
)}
|
||||||
)
|
|
||||||
}
|
|
||||||
{tooltipContent}
|
{tooltipContent}
|
||||||
</div>
|
</div>
|
||||||
<div className={`grid grid-cols-${options?.length} gap-3`}>
|
<div className={`grid grid-cols-${options?.length} gap-3`}>
|
||||||
{
|
{options.filter((option) => {
|
||||||
options.filter((option) => {
|
if (option.show_on.length)
|
||||||
if (option.show_on.length)
|
return option.show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value)
|
||||||
return option.show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value)
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}).map(option => (
|
}).map(option => (
|
||||||
<div
|
<div
|
||||||
className={`
|
className={`
|
||||||
flex items-center gap-2 px-3 py-2 rounded-lg border border-components-option-card-option-border bg-components-option-card-option-bg cursor-pointer
|
flex items-center gap-2 px-3 py-2 rounded-lg border border-components-option-card-option-border bg-components-option-card-option-bg cursor-pointer
|
||||||
${value[variable] === option.value && 'bg-components-option-card-option-selected-bg border-[1.5px] border-components-option-card-option-selected-border shadow-sm'}
|
${value[variable] === option.value && 'bg-components-option-card-option-selected-bg border-[1.5px] border-components-option-card-option-selected-border shadow-sm'}
|
||||||
${disabled && '!cursor-not-allowed opacity-60'}
|
${disabled && '!cursor-not-allowed opacity-60'}
|
||||||
`}
|
`}
|
||||||
onClick={() => handleFormChange(variable, option.value)}
|
onClick={() => handleFormChange(variable, option.value)}
|
||||||
key={`${variable}-${option.value}`}
|
key={`${variable}-${option.value}`}
|
||||||
>
|
>
|
||||||
<RadioE isChecked={value[variable] === option.value} />
|
<RadioE isChecked={value[variable] === option.value} />
|
||||||
|
|
||||||
<div className='system-sm-regular text-text-secondary'>{option.label[language] || option.label.en_US}</div>
|
<div className='system-sm-regular text-text-secondary'>{option.label[language] || option.label.en_US}</div>
|
||||||
</div>
|
</div>
|
||||||
))
|
))}
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
{fieldMoreInfo?.(formSchema)}
|
{fieldMoreInfo?.(formSchema)}
|
||||||
{validating && changeKey === variable && <ValidatingTip />}
|
{validating && changeKey === variable && <ValidatingTip />}
|
||||||
@ -190,12 +179,7 @@ const Form: FC<FormProps> = ({
|
|||||||
|
|
||||||
if (formSchema.type === FormTypeEnum.select) {
|
if (formSchema.type === FormTypeEnum.select) {
|
||||||
const {
|
const {
|
||||||
options,
|
options, variable, label, show_on, required, placeholder,
|
||||||
variable,
|
|
||||||
label,
|
|
||||||
show_on,
|
|
||||||
required,
|
|
||||||
placeholder,
|
|
||||||
} = formSchema as CredentialFormSchemaSelect
|
} = formSchema as CredentialFormSchemaSelect
|
||||||
|
|
||||||
if (show_on.length && !show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value))
|
if (show_on.length && !show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value))
|
||||||
@ -206,11 +190,9 @@ const Form: FC<FormProps> = ({
|
|||||||
<div className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-semibold text-text-secondary')}>
|
<div className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-semibold text-text-secondary')}>
|
||||||
{label[language] || label.en_US}
|
{label[language] || label.en_US}
|
||||||
|
|
||||||
{
|
{required && (
|
||||||
required && (
|
<span className='ml-1 text-red-500'>*</span>
|
||||||
<span className='ml-1 text-red-500'>*</span>
|
)}
|
||||||
)
|
|
||||||
}
|
|
||||||
{tooltipContent}
|
{tooltipContent}
|
||||||
</div>
|
</div>
|
||||||
<SimpleSelect
|
<SimpleSelect
|
||||||
@ -225,8 +207,7 @@ const Form: FC<FormProps> = ({
|
|||||||
return true
|
return true
|
||||||
}).map(option => ({ value: option.value, name: option.label[language] || option.label.en_US }))}
|
}).map(option => ({ value: option.value, name: option.label[language] || option.label.en_US }))}
|
||||||
onSelect={item => handleFormChange(variable, item.value as string)}
|
onSelect={item => handleFormChange(variable, item.value as string)}
|
||||||
placeholder={placeholder?.[language] || placeholder?.en_US}
|
placeholder={placeholder?.[language] || placeholder?.en_US} />
|
||||||
/>
|
|
||||||
{fieldMoreInfo?.(formSchema)}
|
{fieldMoreInfo?.(formSchema)}
|
||||||
{validating && changeKey === variable && <ValidatingTip />}
|
{validating && changeKey === variable && <ValidatingTip />}
|
||||||
</div>
|
</div>
|
||||||
@ -235,10 +216,7 @@ const Form: FC<FormProps> = ({
|
|||||||
|
|
||||||
if (formSchema.type === FormTypeEnum.boolean) {
|
if (formSchema.type === FormTypeEnum.boolean) {
|
||||||
const {
|
const {
|
||||||
variable,
|
variable, label, show_on, required,
|
||||||
label,
|
|
||||||
show_on,
|
|
||||||
required,
|
|
||||||
} = formSchema as CredentialFormSchemaRadio
|
} = formSchema as CredentialFormSchemaRadio
|
||||||
|
|
||||||
if (show_on.length && !show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value))
|
if (show_on.length && !show_on.every(showOnItem => value[showOnItem.variable] === showOnItem.value))
|
||||||
@ -249,11 +227,9 @@ const Form: FC<FormProps> = ({
|
|||||||
<div className='flex items-center justify-between py-2 system-sm-semibold text-text-secondary'>
|
<div className='flex items-center justify-between py-2 system-sm-semibold text-text-secondary'>
|
||||||
<div className='flex items-center space-x-2'>
|
<div className='flex items-center space-x-2'>
|
||||||
<span className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-regular text-text-secondary')}>{label[language] || label.en_US}</span>
|
<span className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-regular text-text-secondary')}>{label[language] || label.en_US}</span>
|
||||||
{
|
{required && (
|
||||||
required && (
|
<span className='ml-1 text-red-500'>*</span>
|
||||||
<span className='ml-1 text-red-500'>*</span>
|
)}
|
||||||
)
|
|
||||||
}
|
|
||||||
{tooltipContent}
|
{tooltipContent}
|
||||||
</div>
|
</div>
|
||||||
<Radio.Group
|
<Radio.Group
|
||||||
@ -272,20 +248,15 @@ const Form: FC<FormProps> = ({
|
|||||||
|
|
||||||
if (formSchema.type === FormTypeEnum.modelSelector) {
|
if (formSchema.type === FormTypeEnum.modelSelector) {
|
||||||
const {
|
const {
|
||||||
variable,
|
variable, label, required, scope,
|
||||||
label,
|
|
||||||
required,
|
|
||||||
scope,
|
|
||||||
} = formSchema as (CredentialFormSchemaTextInput | CredentialFormSchemaSecretInput)
|
} = formSchema as (CredentialFormSchemaTextInput | CredentialFormSchemaSecretInput)
|
||||||
return (
|
return (
|
||||||
<div key={variable} className={cn(itemClassName, 'py-3')}>
|
<div key={variable} className={cn(itemClassName, 'py-3')}>
|
||||||
<div className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-semibold text-text-secondary')}>
|
<div className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-semibold text-text-secondary')}>
|
||||||
{label[language] || label.en_US}
|
{label[language] || label.en_US}
|
||||||
{
|
{required && (
|
||||||
required && (
|
<span className='ml-1 text-red-500'>*</span>
|
||||||
<span className='ml-1 text-red-500'>*</span>
|
)}
|
||||||
)
|
|
||||||
}
|
|
||||||
{tooltipContent}
|
{tooltipContent}
|
||||||
</div>
|
</div>
|
||||||
<ModelParameterModal
|
<ModelParameterModal
|
||||||
@ -295,8 +266,7 @@ const Form: FC<FormProps> = ({
|
|||||||
value={value[variable]}
|
value={value[variable]}
|
||||||
setModel={model => handleModelChanged(variable, model)}
|
setModel={model => handleModelChanged(variable, model)}
|
||||||
readonly={readonly}
|
readonly={readonly}
|
||||||
scope={scope}
|
scope={scope} />
|
||||||
/>
|
|
||||||
{fieldMoreInfo?.(formSchema)}
|
{fieldMoreInfo?.(formSchema)}
|
||||||
{validating && changeKey === variable && <ValidatingTip />}
|
{validating && changeKey === variable && <ValidatingTip />}
|
||||||
</div>
|
</div>
|
||||||
@ -305,27 +275,22 @@ const Form: FC<FormProps> = ({
|
|||||||
|
|
||||||
if (formSchema.type === FormTypeEnum.toolSelector) {
|
if (formSchema.type === FormTypeEnum.toolSelector) {
|
||||||
const {
|
const {
|
||||||
variable,
|
variable, label, required,
|
||||||
label,
|
|
||||||
required,
|
|
||||||
} = formSchema as (CredentialFormSchemaTextInput | CredentialFormSchemaSecretInput)
|
} = formSchema as (CredentialFormSchemaTextInput | CredentialFormSchemaSecretInput)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={variable} className={cn(itemClassName, 'py-3')}>
|
<div key={variable} className={cn(itemClassName, 'py-3')}>
|
||||||
<div className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-semibold text-text-secondary')}>
|
<div className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-semibold text-text-secondary')}>
|
||||||
{label[language] || label.en_US}
|
{label[language] || label.en_US}
|
||||||
{
|
{required && (
|
||||||
required && (
|
<span className='ml-1 text-red-500'>*</span>
|
||||||
<span className='ml-1 text-red-500'>*</span>
|
)}
|
||||||
)
|
|
||||||
}
|
|
||||||
{tooltipContent}
|
{tooltipContent}
|
||||||
</div>
|
</div>
|
||||||
<ToolSelector
|
<ToolSelector
|
||||||
disabled={readonly}
|
disabled={readonly}
|
||||||
value={value[variable]}
|
value={value[variable]}
|
||||||
onSelect={item => handleFormChange(variable, item as any)}
|
onSelect={item => handleFormChange(variable, item as any)} />
|
||||||
/>
|
|
||||||
{fieldMoreInfo?.(formSchema)}
|
{fieldMoreInfo?.(formSchema)}
|
||||||
{validating && changeKey === variable && <ValidatingTip />}
|
{validating && changeKey === variable && <ValidatingTip />}
|
||||||
</div>
|
</div>
|
||||||
@ -334,41 +299,54 @@ const Form: FC<FormProps> = ({
|
|||||||
|
|
||||||
if (formSchema.type === FormTypeEnum.appSelector) {
|
if (formSchema.type === FormTypeEnum.appSelector) {
|
||||||
const {
|
const {
|
||||||
variable,
|
variable, label, required, scope,
|
||||||
label,
|
|
||||||
required,
|
|
||||||
scope,
|
|
||||||
} = formSchema as (CredentialFormSchemaTextInput | CredentialFormSchemaSecretInput)
|
} = formSchema as (CredentialFormSchemaTextInput | CredentialFormSchemaSecretInput)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={variable} className={cn(itemClassName, 'py-3')}>
|
<div key={variable} className={cn(itemClassName, 'py-3')}>
|
||||||
<div className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-semibold text-text-secondary')}>
|
<div className={cn(fieldLabelClassName, 'flex items-center py-2 system-sm-semibold text-text-secondary')}>
|
||||||
{label[language] || label.en_US}
|
{label[language] || label.en_US}
|
||||||
{
|
{required && (
|
||||||
required && (
|
<span className='ml-1 text-red-500'>*</span>
|
||||||
<span className='ml-1 text-red-500'>*</span>
|
)}
|
||||||
)
|
|
||||||
}
|
|
||||||
{tooltipContent}
|
{tooltipContent}
|
||||||
</div>
|
</div>
|
||||||
<AppSelector
|
<AppSelector
|
||||||
disabled={readonly}
|
disabled={readonly}
|
||||||
scope={scope}
|
scope={scope}
|
||||||
value={value[variable]}
|
value={value[variable]}
|
||||||
onSelect={item => handleFormChange(variable, { ...item, type: FormTypeEnum.appSelector } as any)}
|
onSelect={item => handleFormChange(variable, { ...item, type: FormTypeEnum.appSelector } as any)} />
|
||||||
/>
|
|
||||||
{fieldMoreInfo?.(formSchema)}
|
{fieldMoreInfo?.(formSchema)}
|
||||||
{validating && changeKey === variable && <ValidatingTip />}
|
{validating && changeKey === variable && <ValidatingTip />}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-expect-error it work
|
||||||
|
if (!Object.values(FormTypeEnum).includes(formSchema.type)) {
|
||||||
|
return customRenderField?.(formSchema as CustomFormSchema, {
|
||||||
|
className,
|
||||||
|
itemClassName,
|
||||||
|
fieldLabelClassName,
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
formSchemas,
|
||||||
|
validating,
|
||||||
|
validatedSuccess,
|
||||||
|
showOnVariableMap,
|
||||||
|
isEditMode,
|
||||||
|
readonly,
|
||||||
|
inputClassName,
|
||||||
|
isShowDefaultValue,
|
||||||
|
fieldMoreInfo,
|
||||||
|
customRenderField,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={className}>
|
<div className={className}>
|
||||||
{
|
{formSchemas.map(formSchema => renderField(formSchema))}
|
||||||
formSchemas.map(formSchema => renderField(formSchema))
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,6 +6,10 @@ import Link from 'next/link'
|
|||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import Form from '@/app/components/header/account-setting/model-provider-page/model-modal/Form'
|
import Form from '@/app/components/header/account-setting/model-provider-page/model-modal/Form'
|
||||||
import { Agent } from '@/app/components/base/icons/src/vender/workflow'
|
import { Agent } from '@/app/components/base/icons/src/vender/workflow'
|
||||||
|
import { InputNumber } from '@/app/components/base/input-number'
|
||||||
|
import Slider from '@/app/components/base/slider'
|
||||||
|
import Field from './field'
|
||||||
|
import type { ComponentProps } from 'react'
|
||||||
|
|
||||||
export type Strategy = {
|
export type Strategy = {
|
||||||
agent_strategy_provider_name: string
|
agent_strategy_provider_name: string
|
||||||
@ -22,22 +26,65 @@ export type AgentStrategyProps = {
|
|||||||
onFormValueChange: (value: ToolVarInputs) => void
|
onFormValueChange: (value: ToolVarInputs) => void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MaxIterFormSchema = Omit<CredentialFormSchema, 'type'> & { type: 'max-iter' }
|
||||||
|
|
||||||
export const AgentStrategy = (props: AgentStrategyProps) => {
|
export const AgentStrategy = (props: AgentStrategyProps) => {
|
||||||
const { strategy, onStrategyChange, formSchema, formValue, onFormValueChange } = props
|
const { strategy, onStrategyChange, formSchema, formValue, onFormValueChange } = props
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const renderField: ComponentProps<typeof Form<MaxIterFormSchema>>['customRenderField'] = (schema, props) => {
|
||||||
|
switch (schema.type) {
|
||||||
|
case 'max-iter': {
|
||||||
|
const value = props.value[schema.variable]
|
||||||
|
const onChange = (value: number) => {
|
||||||
|
props.onChange({ ...props.value, [schema.variable]: value })
|
||||||
|
}
|
||||||
|
return <Field title={t('workflow.nodes.agent.maxIterations')} tooltip={'max iter'} inline>
|
||||||
|
<div className='flex w-[200px] items-center gap-3'>
|
||||||
|
<Slider value={value} onChange={onChange} className='w-full' min={1} max={10} />
|
||||||
|
<InputNumber
|
||||||
|
value={value}
|
||||||
|
// TODO: maybe empty, handle this
|
||||||
|
onChange={onChange as any}
|
||||||
|
defaultValue={3}
|
||||||
|
size='sm'
|
||||||
|
min={1}
|
||||||
|
max={10}
|
||||||
|
className='w-12'
|
||||||
|
placeholder=''
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Field>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(formSchema)
|
||||||
return <div className='space-y-2'>
|
return <div className='space-y-2'>
|
||||||
<AgentStrategySelector value={strategy} onChange={onStrategyChange} />
|
<AgentStrategySelector value={strategy} onChange={onStrategyChange} />
|
||||||
{
|
{
|
||||||
strategy
|
strategy
|
||||||
? <div>
|
? <div>
|
||||||
<Form
|
<Form<MaxIterFormSchema>
|
||||||
formSchemas={formSchema}
|
formSchemas={[
|
||||||
|
...formSchema,
|
||||||
|
{
|
||||||
|
type: 'max-iter',
|
||||||
|
variable: 'max_iterations',
|
||||||
|
label: {
|
||||||
|
en_US: 'Max Iterations',
|
||||||
|
zh_Hans: '最大迭代次数',
|
||||||
|
},
|
||||||
|
name: 'max iter',
|
||||||
|
required: true,
|
||||||
|
show_on: [],
|
||||||
|
} as MaxIterFormSchema,
|
||||||
|
]}
|
||||||
value={formValue}
|
value={formValue}
|
||||||
onChange={onFormValueChange}
|
onChange={onFormValueChange}
|
||||||
validating={false}
|
validating={false}
|
||||||
showOnVariableMap={{}}
|
showOnVariableMap={{}}
|
||||||
isEditMode={true}
|
isEditMode={true}
|
||||||
fieldLabelClassName='uppercase'
|
fieldLabelClassName='uppercase'
|
||||||
|
customRenderField={renderField}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
: <ListEmpty
|
: <ListEmpty
|
||||||
|
|||||||
@ -2,8 +2,6 @@ import type { FC } from 'react'
|
|||||||
import type { NodePanelProps } from '../../types'
|
import type { NodePanelProps } from '../../types'
|
||||||
import type { AgentNodeType } from './types'
|
import type { AgentNodeType } from './types'
|
||||||
import Field from '../_base/components/field'
|
import Field from '../_base/components/field'
|
||||||
import { InputNumber } from '@/app/components/base/input-number'
|
|
||||||
import Slider from '@/app/components/base/slider'
|
|
||||||
import { AgentStrategy } from '../_base/components/agent-strategy'
|
import { AgentStrategy } from '../_base/components/agent-strategy'
|
||||||
import useConfig from './use-config'
|
import useConfig from './use-config'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
@ -43,25 +41,6 @@ const AgentPanel: FC<NodePanelProps<AgentNodeType>> = (props) => {
|
|||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</Field>
|
</Field>
|
||||||
<Field title={t('workflow.nodes.agent.tools')} className='px-4'>
|
|
||||||
|
|
||||||
</Field>
|
|
||||||
<Field title={t('workflow.nodes.agent.maxIterations')} tooltip={'max iter'} inline className='px-4'>
|
|
||||||
<div className='flex w-[200px] items-center gap-3'>
|
|
||||||
<Slider value={iter} onChange={setIter} className='w-full' min={1} max={10} />
|
|
||||||
<InputNumber
|
|
||||||
value={iter}
|
|
||||||
// TODO: maybe empty, handle this
|
|
||||||
onChange={setIter as any}
|
|
||||||
defaultValue={3}
|
|
||||||
size='sm'
|
|
||||||
min={1}
|
|
||||||
max={10}
|
|
||||||
className='w-12'
|
|
||||||
placeholder=''
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</Field>
|
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user