mirror of
https://github.com/langgenius/dify.git
synced 2026-05-13 08:57:28 +08:00
132 lines
3.8 KiB
TypeScript
132 lines
3.8 KiB
TypeScript
import type { Emoji, WorkflowToolProviderParameter, WorkflowToolProviderRequest } from '../types'
|
|
import type { WorkflowToolModalProps } from './types'
|
|
import { produce } from 'immer'
|
|
import { useCallback, useMemo, useState } from 'react'
|
|
import { useTranslation } from 'react-i18next'
|
|
import { toast } from '@/app/components/base/ui/toast'
|
|
import { buildWorkflowOutputParameters } from './utils'
|
|
|
|
export const isWorkflowToolNameValid = (name: string) => {
|
|
if (name === '')
|
|
return true
|
|
|
|
return /^\w+$/.test(name)
|
|
}
|
|
|
|
type UseWorkflowToolFormOptions = Pick<WorkflowToolModalProps, 'isAdd' | 'onCreate' | 'onSave' | 'payload'>
|
|
|
|
export const useWorkflowToolForm = ({
|
|
isAdd,
|
|
onCreate,
|
|
onSave,
|
|
payload,
|
|
}: UseWorkflowToolFormOptions) => {
|
|
const { t } = useTranslation()
|
|
const [showEmojiPicker, setShowEmojiPicker] = useState(false)
|
|
const [showConfirmModal, setShowConfirmModal] = useState(false)
|
|
const [emoji, setEmoji] = useState<Emoji>(payload.icon)
|
|
const [label, setLabel] = useState(payload.label)
|
|
const [name, setName] = useState(payload.name)
|
|
const [description, setDescription] = useState(payload.description)
|
|
const [parameters, setParameters] = useState<WorkflowToolProviderParameter[]>(payload.parameters)
|
|
const [labels, setLabels] = useState<string[]>(payload.labels)
|
|
const [privacyPolicy, setPrivacyPolicy] = useState(payload.privacy_policy)
|
|
|
|
const outputParameters = useMemo(
|
|
() => buildWorkflowOutputParameters(payload.outputParameters, payload.tool?.output_schema),
|
|
[payload.outputParameters, payload.tool?.output_schema],
|
|
)
|
|
const isNameCurrentlyValid = isWorkflowToolNameValid(name)
|
|
|
|
const handleParameterChange = useCallback((key: 'description' | 'form', value: string, index: number) => {
|
|
setParameters(current => produce(current, (draft) => {
|
|
const parameter = draft[index]
|
|
if (!parameter)
|
|
return
|
|
|
|
if (key === 'description')
|
|
parameter.description = value
|
|
else
|
|
parameter.form = value
|
|
}))
|
|
}, [])
|
|
|
|
const handleConfirm = useCallback(() => {
|
|
let errorMessage = ''
|
|
if (!label)
|
|
errorMessage = t('errorMsg.fieldRequired', { ns: 'common', field: t('createTool.name', { ns: 'tools' }) })
|
|
|
|
if (!name)
|
|
errorMessage = t('errorMsg.fieldRequired', { ns: 'common', field: t('createTool.nameForToolCall', { ns: 'tools' }) })
|
|
|
|
if (!isWorkflowToolNameValid(name))
|
|
errorMessage = t('createTool.nameForToolCall', { ns: 'tools' }) + t('createTool.nameForToolCallTip', { ns: 'tools' })
|
|
|
|
if (errorMessage) {
|
|
toast.error(errorMessage)
|
|
return
|
|
}
|
|
|
|
const requestParams: WorkflowToolProviderRequest = {
|
|
name,
|
|
description,
|
|
icon: emoji,
|
|
label,
|
|
parameters: parameters.map(item => ({
|
|
name: item.name,
|
|
description: item.description,
|
|
form: item.form,
|
|
})),
|
|
labels,
|
|
privacy_policy: privacyPolicy,
|
|
}
|
|
|
|
if (isAdd) {
|
|
onCreate?.({
|
|
...requestParams,
|
|
workflow_app_id: payload.workflow_app_id!,
|
|
})
|
|
return
|
|
}
|
|
|
|
onSave?.({
|
|
...requestParams,
|
|
workflow_tool_id: payload.workflow_tool_id!,
|
|
})
|
|
}, [description, emoji, isAdd, label, labels, name, onCreate, onSave, parameters, payload.workflow_app_id, payload.workflow_tool_id, privacyPolicy, t])
|
|
|
|
const handlePrimaryAction = useCallback(() => {
|
|
if (isAdd) {
|
|
handleConfirm()
|
|
return
|
|
}
|
|
|
|
setShowConfirmModal(true)
|
|
}, [handleConfirm, isAdd])
|
|
|
|
return {
|
|
description,
|
|
emoji,
|
|
handleConfirm,
|
|
handleParameterChange,
|
|
handlePrimaryAction,
|
|
isNameCurrentlyValid,
|
|
label,
|
|
labels,
|
|
name,
|
|
outputParameters,
|
|
parameters,
|
|
privacyPolicy,
|
|
setDescription,
|
|
setEmoji,
|
|
setLabel,
|
|
setLabels,
|
|
setName,
|
|
setPrivacyPolicy,
|
|
setShowConfirmModal,
|
|
setShowEmojiPicker,
|
|
showConfirmModal,
|
|
showEmojiPicker,
|
|
}
|
|
}
|