use-config.ts 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. import { useCallback, useEffect, useMemo, useState } from 'react'
  2. import { useTranslation } from 'react-i18next'
  3. import produce from 'immer'
  4. import { useBoolean } from 'ahooks'
  5. import { useStore } from '../../store'
  6. import { type ToolNodeType, type ToolVarInputs, VarType } from './types'
  7. import { useLanguage } from '@/app/components/header/account-setting/model-provider-page/hooks'
  8. import useNodeCrud from '@/app/components/workflow/nodes/_base/hooks/use-node-crud'
  9. import { CollectionType } from '@/app/components/tools/types'
  10. import { updateBuiltInToolCredential } from '@/service/tools'
  11. import { addDefaultValue, toolParametersToFormSchemas } from '@/app/components/tools/utils/to-form-schema'
  12. import Toast from '@/app/components/base/toast'
  13. import type { Props as FormProps } from '@/app/components/workflow/nodes/_base/components/before-run-form/form'
  14. import { VarType as VarVarType } from '@/app/components/workflow/types'
  15. import type { InputVar, ValueSelector, Var } from '@/app/components/workflow/types'
  16. import useOneStepRun from '@/app/components/workflow/nodes/_base/hooks/use-one-step-run'
  17. import {
  18. useFetchToolsData,
  19. useNodesReadOnly,
  20. } from '@/app/components/workflow/hooks'
  21. const useConfig = (id: string, payload: ToolNodeType) => {
  22. const { nodesReadOnly: readOnly } = useNodesReadOnly()
  23. const { handleFetchAllTools } = useFetchToolsData()
  24. const { t } = useTranslation()
  25. const language = useLanguage()
  26. const { inputs, setInputs: doSetInputs } = useNodeCrud<ToolNodeType>(id, payload)
  27. /*
  28. * tool_configurations: tool setting, not dynamic setting
  29. * tool_parameters: tool dynamic setting(by user)
  30. */
  31. const { provider_id, provider_type, tool_name, tool_configurations } = inputs
  32. const isBuiltIn = provider_type === CollectionType.builtIn
  33. const buildInTools = useStore(s => s.buildInTools)
  34. const customTools = useStore(s => s.customTools)
  35. const currentTools = isBuiltIn ? buildInTools : customTools
  36. const currCollection = currentTools.find(item => item.id === provider_id)
  37. // Auth
  38. const needAuth = !!currCollection?.allow_delete
  39. const isAuthed = !!currCollection?.is_team_authorization
  40. const isShowAuthBtn = isBuiltIn && needAuth && !isAuthed
  41. const [showSetAuth, {
  42. setTrue: showSetAuthModal,
  43. setFalse: hideSetAuthModal,
  44. }] = useBoolean(false)
  45. const handleSaveAuth = useCallback(async (value: any) => {
  46. await updateBuiltInToolCredential(currCollection?.name as string, value)
  47. Toast.notify({
  48. type: 'success',
  49. message: t('common.api.actionSuccess'),
  50. })
  51. handleFetchAllTools(provider_type)
  52. hideSetAuthModal()
  53. }, [currCollection?.name, hideSetAuthModal, t, handleFetchAllTools, provider_type])
  54. const currTool = currCollection?.tools.find(tool => tool.name === tool_name)
  55. const formSchemas = useMemo(() => {
  56. return currTool ? toolParametersToFormSchemas(currTool.parameters) : []
  57. }, [currTool])
  58. const toolInputVarSchema = formSchemas.filter((item: any) => item.form === 'llm')
  59. // use setting
  60. const toolSettingSchema = formSchemas.filter((item: any) => item.form !== 'llm')
  61. const hasShouldTransferTypeSettingInput = toolSettingSchema.some(item => item.type === 'boolean' || item.type === 'number-input')
  62. const setInputs = useCallback((value: ToolNodeType) => {
  63. if (!hasShouldTransferTypeSettingInput) {
  64. doSetInputs(value)
  65. return
  66. }
  67. const newInputs = produce(value, (draft) => {
  68. const newConfig = { ...draft.tool_configurations }
  69. Object.keys(draft.tool_configurations).forEach((key) => {
  70. const schema = formSchemas.find(item => item.variable === key)
  71. const value = newConfig[key]
  72. if (schema?.type === 'boolean') {
  73. if (typeof value === 'string')
  74. newConfig[key] = parseInt(value, 10)
  75. if (typeof value === 'boolean')
  76. newConfig[key] = value ? 1 : 0
  77. }
  78. if (schema?.type === 'number-input') {
  79. if (typeof value === 'string' && value !== '')
  80. newConfig[key] = parseFloat(value)
  81. }
  82. })
  83. draft.tool_configurations = newConfig
  84. })
  85. doSetInputs(newInputs)
  86. }, [doSetInputs, formSchemas, hasShouldTransferTypeSettingInput])
  87. const [notSetDefaultValue, setNotSetDefaultValue] = useState(false)
  88. const toolSettingValue = (() => {
  89. if (notSetDefaultValue)
  90. return tool_configurations
  91. return addDefaultValue(tool_configurations, toolSettingSchema)
  92. })()
  93. const setToolSettingValue = useCallback((value: Record<string, any>) => {
  94. setNotSetDefaultValue(true)
  95. setInputs({
  96. ...inputs,
  97. tool_configurations: value,
  98. })
  99. }, [inputs, setInputs])
  100. useEffect(() => {
  101. if (!currTool)
  102. return
  103. const inputsWithDefaultValue = produce(inputs, (draft) => {
  104. if (!draft.tool_configurations || Object.keys(draft.tool_configurations).length === 0)
  105. draft.tool_configurations = addDefaultValue(tool_configurations, toolSettingSchema)
  106. if (!draft.tool_parameters)
  107. draft.tool_parameters = {}
  108. })
  109. setInputs(inputsWithDefaultValue)
  110. // eslint-disable-next-line react-hooks/exhaustive-deps
  111. }, [currTool])
  112. // setting when call
  113. const setInputVar = useCallback((value: ToolVarInputs) => {
  114. setInputs({
  115. ...inputs,
  116. tool_parameters: value,
  117. })
  118. }, [inputs, setInputs])
  119. const [currVarIndex, setCurrVarIndex] = useState(-1)
  120. const currVarType = toolInputVarSchema[currVarIndex]?._type
  121. const handleOnVarOpen = useCallback((index: number) => {
  122. setCurrVarIndex(index)
  123. }, [])
  124. const filterVar = useCallback((varPayload: Var) => {
  125. if (currVarType)
  126. return varPayload.type === currVarType
  127. return varPayload.type !== VarVarType.arrayFile
  128. }, [currVarType])
  129. const isLoading = currTool && (isBuiltIn ? !currCollection : false)
  130. // single run
  131. const [inputVarValues, doSetInputVarValues] = useState<Record<string, any>>({})
  132. const setInputVarValues = (value: Record<string, any>) => {
  133. doSetInputVarValues(value)
  134. // eslint-disable-next-line @typescript-eslint/no-use-before-define
  135. setRunInputData(value)
  136. }
  137. // fill single run form variable with constant value first time
  138. const inputVarValuesWithConstantValue = () => {
  139. const res = produce(inputVarValues, (draft) => {
  140. Object.keys(inputs.tool_parameters).forEach((key: string) => {
  141. const { type, value } = inputs.tool_parameters[key]
  142. if (type === VarType.constant && (value === undefined || value === null))
  143. draft.tool_parameters[key].value = value
  144. })
  145. })
  146. return res
  147. }
  148. const {
  149. isShowSingleRun,
  150. hideSingleRun,
  151. getInputVars,
  152. runningStatus,
  153. setRunInputData,
  154. handleRun: doHandleRun,
  155. handleStop,
  156. runResult,
  157. } = useOneStepRun<ToolNodeType>({
  158. id,
  159. data: inputs,
  160. defaultRunInputData: {},
  161. moreDataForCheckValid: {
  162. toolInputsSchema: (() => {
  163. const formInputs: InputVar[] = []
  164. toolInputVarSchema.forEach((item: any) => {
  165. formInputs.push({
  166. label: item.label[language] || item.label.en_US,
  167. variable: item.variable,
  168. type: item.type,
  169. required: item.required,
  170. })
  171. })
  172. return formInputs
  173. })(),
  174. notAuthed: isShowAuthBtn,
  175. toolSettingSchema,
  176. language,
  177. },
  178. })
  179. const hadVarParams = Object.keys(inputs.tool_parameters)
  180. .filter(key => inputs.tool_parameters[key].type !== VarType.constant)
  181. .map(k => inputs.tool_parameters[k])
  182. const varInputs = getInputVars(hadVarParams.map((p) => {
  183. if (p.type === VarType.variable)
  184. return `{{#${(p.value as ValueSelector).join('.')}#}}`
  185. return p.value as string
  186. }))
  187. const singleRunForms = (() => {
  188. const forms: FormProps[] = [{
  189. inputs: varInputs,
  190. values: inputVarValuesWithConstantValue(),
  191. onChange: setInputVarValues,
  192. }]
  193. return forms
  194. })()
  195. const handleRun = (submitData: Record<string, any>) => {
  196. const varTypeInputKeys = Object.keys(inputs.tool_parameters)
  197. .filter(key => inputs.tool_parameters[key].type === VarType.variable)
  198. const shouldAdd = varTypeInputKeys.length > 0
  199. if (!shouldAdd) {
  200. doHandleRun(submitData)
  201. return
  202. }
  203. const addMissedVarData = { ...submitData }
  204. Object.keys(submitData).forEach((key) => {
  205. const value = submitData[key]
  206. varTypeInputKeys.forEach((inputKey) => {
  207. const inputValue = inputs.tool_parameters[inputKey].value as ValueSelector
  208. if (`#${inputValue.join('.')}#` === key)
  209. addMissedVarData[inputKey] = value
  210. })
  211. })
  212. doHandleRun(addMissedVarData)
  213. }
  214. return {
  215. readOnly,
  216. inputs,
  217. currTool,
  218. toolSettingSchema,
  219. toolSettingValue,
  220. setToolSettingValue,
  221. toolInputVarSchema,
  222. setInputVar,
  223. handleOnVarOpen,
  224. filterVar,
  225. currCollection,
  226. isShowAuthBtn,
  227. showSetAuth,
  228. showSetAuthModal,
  229. hideSetAuthModal,
  230. handleSaveAuth,
  231. isLoading,
  232. isShowSingleRun,
  233. hideSingleRun,
  234. inputVarValues,
  235. varInputs,
  236. setInputVarValues,
  237. singleRunForms,
  238. runningStatus,
  239. handleRun,
  240. handleStop,
  241. runResult,
  242. }
  243. }
  244. export default useConfig