mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-15 04:05:55 +08:00
fix: can add a custom tool without a name (#6172)
This commit is contained in:
parent
5660878f7b
commit
27d72e30ad
@ -17,6 +17,7 @@ import EmojiPicker from '@/app/components/base/emoji-picker'
|
|||||||
import AppIcon from '@/app/components/base/app-icon'
|
import AppIcon from '@/app/components/base/app-icon'
|
||||||
import { parseParamsSchema } from '@/service/tools'
|
import { parseParamsSchema } from '@/service/tools'
|
||||||
import LabelSelector from '@/app/components/tools/labels/selector'
|
import LabelSelector from '@/app/components/tools/labels/selector'
|
||||||
|
import Toast from '@/app/components/base/toast'
|
||||||
|
|
||||||
const fieldNameClassNames = 'py-2 leading-5 text-sm font-medium text-gray-900'
|
const fieldNameClassNames = 'py-2 leading-5 text-sm font-medium text-gray-900'
|
||||||
type Props = {
|
type Props = {
|
||||||
@ -136,6 +137,21 @@ const EditCustomCollectionModal: FC<Props> = ({
|
|||||||
draft.labels = labels
|
draft.labels = labels
|
||||||
})
|
})
|
||||||
|
|
||||||
|
let errorMessage = ''
|
||||||
|
if (!postData.provider)
|
||||||
|
errorMessage = t('common.errorMsg.fieldRequired', { field: t('tools.createTool.name') })
|
||||||
|
|
||||||
|
if (!postData.schema)
|
||||||
|
errorMessage = t('common.errorMsg.fieldRequired', { field: t('tools.createTool.schema') })
|
||||||
|
|
||||||
|
if (errorMessage) {
|
||||||
|
Toast.notify({
|
||||||
|
type: 'error',
|
||||||
|
message: errorMessage,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (isAdd) {
|
if (isAdd) {
|
||||||
onAdd?.(postData)
|
onAdd?.(postData)
|
||||||
return
|
return
|
||||||
@ -175,7 +191,7 @@ const EditCustomCollectionModal: FC<Props> = ({
|
|||||||
<div className='flex flex-col h-full'>
|
<div className='flex flex-col h-full'>
|
||||||
<div className='grow h-0 overflow-y-auto px-6 py-3 space-y-4'>
|
<div className='grow h-0 overflow-y-auto px-6 py-3 space-y-4'>
|
||||||
<div>
|
<div>
|
||||||
<div className={fieldNameClassNames}>{t('tools.createTool.name')}</div>
|
<div className={fieldNameClassNames}>{t('tools.createTool.name')} <span className='ml-1 text-red-500'>*</span></div>
|
||||||
<div className='flex items-center justify-between gap-3'>
|
<div className='flex items-center justify-between gap-3'>
|
||||||
<AppIcon size='large' onClick={() => { setShowEmojiPicker(true) }} className='cursor-pointer' icon={emoji.content} background={emoji.background} />
|
<AppIcon size='large' onClick={() => { setShowEmojiPicker(true) }} className='cursor-pointer' icon={emoji.content} background={emoji.background} />
|
||||||
<input
|
<input
|
||||||
@ -195,7 +211,7 @@ const EditCustomCollectionModal: FC<Props> = ({
|
|||||||
<div className='select-none'>
|
<div className='select-none'>
|
||||||
<div className='flex justify-between items-center'>
|
<div className='flex justify-between items-center'>
|
||||||
<div className='flex items-center'>
|
<div className='flex items-center'>
|
||||||
<div className={fieldNameClassNames}>{t('tools.createTool.schema')}</div>
|
<div className={fieldNameClassNames}>{t('tools.createTool.schema')}<span className='ml-1 text-red-500'>*</span></div>
|
||||||
<div className='mx-2 w-px h-3 bg-black/5'></div>
|
<div className='mx-2 w-px h-3 bg-black/5'></div>
|
||||||
<a
|
<a
|
||||||
href="https://swagger.io/specification/"
|
href="https://swagger.io/specification/"
|
||||||
|
@ -63,28 +63,32 @@ const WorkflowToolAsModal: FC<Props> = ({
|
|||||||
const [showModal, setShowModal] = useState(false)
|
const [showModal, setShowModal] = useState(false)
|
||||||
|
|
||||||
const isNameValid = (name: string) => {
|
const isNameValid = (name: string) => {
|
||||||
|
// when the user has not input anything, no need for a warning
|
||||||
|
if (name === '')
|
||||||
|
return true
|
||||||
|
|
||||||
return /^[a-zA-Z0-9_]+$/.test(name)
|
return /^[a-zA-Z0-9_]+$/.test(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onConfirm = () => {
|
const onConfirm = () => {
|
||||||
if (!label) {
|
let errorMessage = ''
|
||||||
return Toast.notify({
|
if (!label)
|
||||||
|
errorMessage = t('common.errorMsg.fieldRequired', { field: t('tools.createTool.name') })
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
errorMessage = t('common.errorMsg.fieldRequired', { field: t('tools.createTool.nameForToolCall') })
|
||||||
|
|
||||||
|
if (!isNameValid(name))
|
||||||
|
errorMessage = t('tools.createTool.nameForToolCall') + t('tools.createTool.nameForToolCallTip')
|
||||||
|
|
||||||
|
if (errorMessage) {
|
||||||
|
Toast.notify({
|
||||||
type: 'error',
|
type: 'error',
|
||||||
message: 'Please enter the tool name',
|
message: errorMessage,
|
||||||
})
|
|
||||||
}
|
|
||||||
if (!name) {
|
|
||||||
return Toast.notify({
|
|
||||||
type: 'error',
|
|
||||||
message: 'Please enter the name for tool call',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
else if (!isNameValid(name)) {
|
|
||||||
return Toast.notify({
|
|
||||||
type: 'error',
|
|
||||||
message: 'Name for tool call can only contain numbers, letters, and underscores',
|
|
||||||
})
|
})
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const requestParams = {
|
const requestParams = {
|
||||||
name,
|
name,
|
||||||
description,
|
description,
|
||||||
@ -127,7 +131,7 @@ const WorkflowToolAsModal: FC<Props> = ({
|
|||||||
<div className='grow h-0 overflow-y-auto px-6 py-3 space-y-4'>
|
<div className='grow h-0 overflow-y-auto px-6 py-3 space-y-4'>
|
||||||
{/* name & icon */}
|
{/* name & icon */}
|
||||||
<div>
|
<div>
|
||||||
<div className='py-2 leading-5 text-sm font-medium text-gray-900'>{t('tools.createTool.name')}</div>
|
<div className='py-2 leading-5 text-sm font-medium text-gray-900'>{t('tools.createTool.name')} <span className='ml-1 text-red-500'>*</span></div>
|
||||||
<div className='flex items-center justify-between gap-3'>
|
<div className='flex items-center justify-between gap-3'>
|
||||||
<AppIcon size='large' onClick={() => { setShowEmojiPicker(true) }} className='cursor-pointer' icon={emoji.content} background={emoji.background} />
|
<AppIcon size='large' onClick={() => { setShowEmojiPicker(true) }} className='cursor-pointer' icon={emoji.content} background={emoji.background} />
|
||||||
<input
|
<input
|
||||||
@ -142,7 +146,7 @@ const WorkflowToolAsModal: FC<Props> = ({
|
|||||||
{/* name for tool call */}
|
{/* name for tool call */}
|
||||||
<div>
|
<div>
|
||||||
<div className='flex items-center py-2 leading-5 text-sm font-medium text-gray-900'>
|
<div className='flex items-center py-2 leading-5 text-sm font-medium text-gray-900'>
|
||||||
{t('tools.createTool.nameForToolCall')}
|
{t('tools.createTool.nameForToolCall')} <span className='ml-1 text-red-500'>*</span>
|
||||||
<Tooltip
|
<Tooltip
|
||||||
htmlContent={
|
htmlContent={
|
||||||
<div className='w-[180px]'>
|
<div className='w-[180px]'>
|
||||||
@ -162,7 +166,7 @@ const WorkflowToolAsModal: FC<Props> = ({
|
|||||||
onChange={e => setName(e.target.value)}
|
onChange={e => setName(e.target.value)}
|
||||||
/>
|
/>
|
||||||
{!isNameValid(name) && (
|
{!isNameValid(name) && (
|
||||||
<div className='text-xs leading-[18px] text-[#DC6803]'>{t('tools.createTool.nameForToolCallTip')}</div>
|
<div className='text-xs leading-[18px] text-red-500'>{t('tools.createTool.nameForToolCallTip')}</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{/* description */}
|
{/* description */}
|
||||||
@ -248,7 +252,7 @@ const WorkflowToolAsModal: FC<Props> = ({
|
|||||||
)}
|
)}
|
||||||
<div className='flex space-x-2 '>
|
<div className='flex space-x-2 '>
|
||||||
<Button onClick={onHide}>{t('common.operation.cancel')}</Button>
|
<Button onClick={onHide}>{t('common.operation.cancel')}</Button>
|
||||||
<Button disabled={!label || !name || !isNameValid(name)} variant='primary' onClick={() => {
|
<Button variant='primary' onClick={() => {
|
||||||
if (isAdd)
|
if (isAdd)
|
||||||
onConfirm()
|
onConfirm()
|
||||||
else
|
else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user