mirror of
https://github.com/langgenius/dify.git
synced 2026-04-30 21:58:00 +08:00
Signed-off-by: majiayu000 <1835304752@qq.com> Signed-off-by: dependabot[bot] <support@github.com> Signed-off-by: NeatGuyCoding <15627489+NeatGuyCoding@users.noreply.github.com> Signed-off-by: -LAN- <laipz8200@outlook.com> Signed-off-by: yihong0618 <zouzou0208@gmail.com> Co-authored-by: QuantumGhost <obelisk.reg+git@gmail.com> Co-authored-by: 盐粒 Yanli <yanli@dify.ai> Co-authored-by: wangxiaolei <fatelei@gmail.com> Co-authored-by: Stephen Zhou <38493346+hyoban@users.noreply.github.com> Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Cursx <33718736+Cursx@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: lif <1835304752@qq.com> Co-authored-by: 非法操作 <hjlarry@163.com> Co-authored-by: Asuka Minato <i@asukaminato.eu.org> Co-authored-by: fenglin <790872612@qq.com> Co-authored-by: qiaofenglin <qiaofenglin@baidu.com> Co-authored-by: -LAN- <laipz8200@outlook.com> Co-authored-by: TomoOkuyama <49631611+TomoOkuyama@users.noreply.github.com> Co-authored-by: Tomo Okuyama <tomo.okuyama@intersystems.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: zyssyz123 <916125788@qq.com> Co-authored-by: hj24 <mambahj24@gmail.com> Co-authored-by: Coding On Star <447357187@qq.com> Co-authored-by: CodingOnStar <hanxujiang@dify.ai> Co-authored-by: yyh <92089059+lyzno1@users.noreply.github.com> Co-authored-by: Xiangxuan Qu <fghpdf@outlook.com> Co-authored-by: fghpdf <fghpdf@users.noreply.github.com> Co-authored-by: coopercoder <whitetiger0127@163.com> Co-authored-by: zhaiguangpeng <zhaiguangpeng@didiglobal.com> Co-authored-by: Junyan Qin (Chin) <rockchinq@gmail.com> Co-authored-by: E.G <146701565+GlobalStar117@users.noreply.github.com> Co-authored-by: GlobalStar117 <GlobalStar117@users.noreply.github.com> Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com> Co-authored-by: CodingOnStar <hanxujiang@dify.com> Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com> Co-authored-by: heyszt <270985384@qq.com> Co-authored-by: NeatGuyCoding <15627489+NeatGuyCoding@users.noreply.github.com> Co-authored-by: Yeuoly <45712896+Yeuoly@users.noreply.github.com> Co-authored-by: zxhlyh <jasonapring2015@outlook.com> Co-authored-by: moonpanda <chuanzegao@163.com> Co-authored-by: warlocgao <warlocgao@tencent.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com> Co-authored-by: KVOJJJin <jzongcode@gmail.com> Co-authored-by: eux <euxx@users.noreply.github.com> Co-authored-by: bangjiehan <bangjiehan@gmail.com> Co-authored-by: FFXN <31929997+FFXN@users.noreply.github.com> Co-authored-by: Jyong <76649700+JohnJyong@users.noreply.github.com> Co-authored-by: Nie Ronghua <nieronghua@sf-express.com> Co-authored-by: JQSevenMiao <141806521+JQSevenMiao@users.noreply.github.com> Co-authored-by: jiasiqi <jiasiqi3@tal.com> Co-authored-by: Seokrin Taron Sung <sungsjade@gmail.com> Co-authored-by: CrabSAMA <40541269+CrabSAMA@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Co-authored-by: yihong <zouzou0208@gmail.com> Co-authored-by: Joel <iamjoel007@gmail.com> Co-authored-by: Wu Tianwei <30284043+WTW0313@users.noreply.github.com> Co-authored-by: yessenia <yessenia.contact@gmail.com> Co-authored-by: Jax <anobaka@qq.com> Co-authored-by: niveshdandyan <155956228+niveshdandyan@users.noreply.github.com> Co-authored-by: OSS Contributor <oss-contributor@example.com> Co-authored-by: niveshdandyan <niveshdandyan@users.noreply.github.com> Co-authored-by: Sean Kenneth Doherty <Smaster7772@gmail.com>
304 lines
9.0 KiB
TypeScript
304 lines
9.0 KiB
TypeScript
import type { ToolNodeType, ToolVarInputs } from './types'
|
|
import type { InputVar } from '@/app/components/workflow/types'
|
|
import { useBoolean } from 'ahooks'
|
|
import { produce } from 'immer'
|
|
import { useCallback, useEffect, useMemo, useState } from 'react'
|
|
import { useTranslation } from 'react-i18next'
|
|
import Toast from '@/app/components/base/toast'
|
|
import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
|
|
import { CollectionType } from '@/app/components/tools/types'
|
|
import {
|
|
getConfiguredValue,
|
|
toolParametersToFormSchemas,
|
|
} from '@/app/components/tools/utils/to-form-schema'
|
|
import {
|
|
useNodesReadOnly,
|
|
} from '@/app/components/workflow/hooks'
|
|
import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
|
|
import { updateBuiltInToolCredential } from '@/service/tools'
|
|
import {
|
|
useAllBuiltInTools,
|
|
useAllCustomTools,
|
|
useAllMCPTools,
|
|
useAllWorkflowTools,
|
|
useInvalidToolsByType,
|
|
} from '@/service/use-tools'
|
|
import { canFindTool } from '@/utils'
|
|
import { useWorkflowStore } from '../../store'
|
|
|
|
const useConfig = (id: string, payload: ToolNodeType) => {
|
|
const workflowStore = useWorkflowStore()
|
|
const { nodesReadOnly: readOnly } = useNodesReadOnly()
|
|
const { t } = useTranslation()
|
|
|
|
const language = useLanguage()
|
|
const { inputs, setInputs: doSetInputs } = useNodeCrud<ToolNodeType>(
|
|
id,
|
|
payload,
|
|
)
|
|
/*
|
|
* tool_configurations: tool setting, not dynamic setting (form type = form)
|
|
* tool_parameters: tool dynamic setting(form type = llm)
|
|
*/
|
|
const {
|
|
provider_id,
|
|
provider_type,
|
|
tool_name,
|
|
tool_configurations,
|
|
tool_parameters,
|
|
} = inputs
|
|
const isBuiltIn = provider_type === CollectionType.builtIn
|
|
const { data: buildInTools } = useAllBuiltInTools()
|
|
const { data: customTools } = useAllCustomTools()
|
|
const { data: workflowTools } = useAllWorkflowTools()
|
|
const { data: mcpTools } = useAllMCPTools()
|
|
|
|
const currentTools = useMemo(() => {
|
|
switch (provider_type) {
|
|
case CollectionType.builtIn:
|
|
return buildInTools || []
|
|
case CollectionType.custom:
|
|
return customTools || []
|
|
case CollectionType.workflow:
|
|
return workflowTools || []
|
|
case CollectionType.mcp:
|
|
return mcpTools || []
|
|
default:
|
|
return []
|
|
}
|
|
}, [buildInTools, customTools, mcpTools, provider_type, workflowTools])
|
|
const currCollection = useMemo(() => {
|
|
return currentTools.find(item => canFindTool(item.id, provider_id))
|
|
}, [currentTools, provider_id])
|
|
|
|
// Auth
|
|
const needAuth = !!currCollection?.allow_delete
|
|
const isAuthed = !!currCollection?.is_team_authorization
|
|
const isShowAuthBtn = isBuiltIn && needAuth && !isAuthed
|
|
const [
|
|
showSetAuth,
|
|
{ setTrue: showSetAuthModal, setFalse: hideSetAuthModal },
|
|
] = useBoolean(false)
|
|
|
|
const invalidToolsByType = useInvalidToolsByType(provider_type)
|
|
const handleSaveAuth = useCallback(
|
|
async (value: any) => {
|
|
await updateBuiltInToolCredential(currCollection?.name as string, value)
|
|
|
|
Toast.notify({
|
|
type: 'success',
|
|
message: t('api.actionSuccess', { ns: 'common' }),
|
|
})
|
|
invalidToolsByType()
|
|
hideSetAuthModal()
|
|
},
|
|
[
|
|
currCollection?.name,
|
|
hideSetAuthModal,
|
|
t,
|
|
invalidToolsByType,
|
|
provider_type,
|
|
],
|
|
)
|
|
|
|
const currTool = useMemo(() => {
|
|
return currCollection?.tools.find(tool => tool.name === tool_name)
|
|
}, [currCollection, tool_name])
|
|
const formSchemas = useMemo(() => {
|
|
return currTool ? toolParametersToFormSchemas(currTool.parameters) : []
|
|
}, [currTool])
|
|
const toolInputVarSchema = useMemo(() => {
|
|
return formSchemas.filter((item: any) => item.form === 'llm')
|
|
}, [formSchemas])
|
|
// use setting
|
|
const toolSettingSchema = useMemo(() => {
|
|
return formSchemas.filter((item: any) => item.form !== 'llm')
|
|
}, [formSchemas])
|
|
const hasShouldTransferTypeSettingInput = toolSettingSchema.some(
|
|
item => item.type === 'boolean' || item.type === 'number-input',
|
|
)
|
|
|
|
const setInputs = useCallback(
|
|
(value: ToolNodeType) => {
|
|
if (!hasShouldTransferTypeSettingInput) {
|
|
doSetInputs(value)
|
|
return
|
|
}
|
|
const newInputs = produce(value, (draft) => {
|
|
const newConfig = { ...draft.tool_configurations }
|
|
Object.keys(draft.tool_configurations).forEach((key) => {
|
|
const schema = formSchemas.find(item => item.variable === key)
|
|
const value = newConfig[key]
|
|
if (schema?.type === 'boolean') {
|
|
if (typeof value === 'string')
|
|
newConfig[key] = value === 'true' || value === '1'
|
|
|
|
if (typeof value === 'number')
|
|
newConfig[key] = value === 1
|
|
}
|
|
|
|
if (schema?.type === 'number-input') {
|
|
if (typeof value === 'string' && value !== '')
|
|
newConfig[key] = Number.parseFloat(value)
|
|
}
|
|
})
|
|
draft.tool_configurations = newConfig
|
|
})
|
|
doSetInputs(newInputs)
|
|
},
|
|
[doSetInputs, formSchemas, hasShouldTransferTypeSettingInput],
|
|
)
|
|
const [notSetDefaultValue, setNotSetDefaultValue] = useState(false)
|
|
const toolSettingValue = useMemo(() => {
|
|
if (notSetDefaultValue)
|
|
return tool_configurations
|
|
return getConfiguredValue(tool_configurations, toolSettingSchema)
|
|
}, [notSetDefaultValue, toolSettingSchema, tool_configurations])
|
|
const setToolSettingValue = useCallback(
|
|
(value: Record<string, any>) => {
|
|
setNotSetDefaultValue(true)
|
|
setInputs({
|
|
...inputs,
|
|
tool_configurations: value,
|
|
})
|
|
},
|
|
[inputs, setInputs],
|
|
)
|
|
|
|
const formattingParameters = () => {
|
|
const inputsWithDefaultValue = produce(inputs, (draft) => {
|
|
if (
|
|
!draft.tool_configurations
|
|
|| Object.keys(draft.tool_configurations).length === 0
|
|
) {
|
|
draft.tool_configurations = getConfiguredValue(
|
|
tool_configurations,
|
|
toolSettingSchema,
|
|
) as ToolVarInputs
|
|
}
|
|
if (
|
|
!draft.tool_parameters
|
|
|| Object.keys(draft.tool_parameters).length === 0
|
|
) {
|
|
draft.tool_parameters = getConfiguredValue(
|
|
tool_parameters,
|
|
toolInputVarSchema,
|
|
) as ToolVarInputs
|
|
}
|
|
})
|
|
return inputsWithDefaultValue
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (!currTool)
|
|
return
|
|
const inputsWithDefaultValue = formattingParameters()
|
|
const { setControlPromptEditorRerenderKey } = workflowStore.getState()
|
|
setInputs(inputsWithDefaultValue)
|
|
setTimeout(() => setControlPromptEditorRerenderKey(Date.now()))
|
|
}, [currTool])
|
|
|
|
// setting when call
|
|
const setInputVar = useCallback(
|
|
(value: ToolVarInputs) => {
|
|
setInputs({
|
|
...inputs,
|
|
tool_parameters: value,
|
|
})
|
|
},
|
|
[inputs, setInputs],
|
|
)
|
|
|
|
const isLoading = currTool && (isBuiltIn ? !currCollection : false)
|
|
|
|
const getMoreDataForCheckValid = () => {
|
|
return {
|
|
toolInputsSchema: (() => {
|
|
const formInputs: InputVar[] = []
|
|
toolInputVarSchema.forEach((item: any) => {
|
|
formInputs.push({
|
|
label: item.label[language] || item.label.en_US,
|
|
variable: item.variable,
|
|
type: item.type,
|
|
required: item.required,
|
|
})
|
|
})
|
|
return formInputs
|
|
})(),
|
|
notAuthed: isShowAuthBtn,
|
|
toolSettingSchema,
|
|
language,
|
|
}
|
|
}
|
|
|
|
const outputSchema = useMemo(() => {
|
|
const res: any[] = []
|
|
const output_schema = currTool?.output_schema
|
|
if (!output_schema || !output_schema.properties)
|
|
return res
|
|
|
|
Object.keys(output_schema.properties).forEach((outputKey) => {
|
|
const output = output_schema.properties[outputKey]
|
|
const type = output.type
|
|
if (type === 'object') {
|
|
res.push({
|
|
name: outputKey,
|
|
value: output,
|
|
})
|
|
}
|
|
else {
|
|
res.push({
|
|
name: outputKey,
|
|
type:
|
|
output.type === 'array'
|
|
? `Array[${output.items?.type
|
|
? output.items.type.slice(0, 1).toLocaleUpperCase()
|
|
+ output.items.type.slice(1)
|
|
: 'Unknown'
|
|
}]`
|
|
: `${output.type
|
|
? output.type.slice(0, 1).toLocaleUpperCase()
|
|
+ output.type.slice(1)
|
|
: 'Unknown'
|
|
}`,
|
|
description: output.description,
|
|
})
|
|
}
|
|
})
|
|
return res
|
|
}, [currTool])
|
|
|
|
const hasObjectOutput = useMemo(() => {
|
|
const output_schema = currTool?.output_schema
|
|
if (!output_schema || !output_schema.properties)
|
|
return false
|
|
const properties = output_schema.properties
|
|
return Object.keys(properties).some(
|
|
key => properties[key].type === 'object',
|
|
)
|
|
}, [currTool])
|
|
|
|
return {
|
|
readOnly,
|
|
inputs,
|
|
currTool,
|
|
toolSettingSchema,
|
|
toolSettingValue,
|
|
setToolSettingValue,
|
|
toolInputVarSchema,
|
|
setInputVar,
|
|
currCollection,
|
|
isShowAuthBtn,
|
|
showSetAuth,
|
|
showSetAuthModal,
|
|
hideSetAuthModal,
|
|
handleSaveAuth,
|
|
isLoading,
|
|
outputSchema,
|
|
hasObjectOutput,
|
|
getMoreDataForCheckValid,
|
|
}
|
|
}
|
|
|
|
export default useConfig
|