Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

use-inspect-vars-crud-common.ts 9.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. import { fetchNodeInspectVars } from '@/service/workflow'
  2. import { useWorkflowStore } from '@/app/components/workflow/store'
  3. import type { ValueSelector } from '@/app/components/workflow/types'
  4. import type { VarInInspect } from '@/types/workflow'
  5. import { VarInInspectType } from '@/types/workflow'
  6. import { useCallback } from 'react'
  7. import {
  8. isConversationVar,
  9. isENV,
  10. isSystemVar,
  11. toNodeOutputVars,
  12. } from '@/app/components/workflow/nodes/_base/components/variable/utils'
  13. import produce from 'immer'
  14. import type { Node } from '@/app/components/workflow/types'
  15. import { useNodesInteractionsWithoutSync } from '@/app/components/workflow/hooks/use-nodes-interactions-without-sync'
  16. import { useEdgesInteractionsWithoutSync } from '@/app/components/workflow/hooks/use-edges-interactions-without-sync'
  17. import type { FlowType } from '@/types/common'
  18. import useFLow from '@/service/use-flow'
  19. import { useStoreApi } from 'reactflow'
  20. import type { SchemaTypeDefinition } from '@/service/use-common'
  21. type Params = {
  22. flowId: string
  23. flowType: FlowType
  24. }
  25. export const useInspectVarsCrudCommon = ({
  26. flowId,
  27. flowType,
  28. }: Params) => {
  29. const workflowStore = useWorkflowStore()
  30. const store = useStoreApi()
  31. const {
  32. useInvalidateConversationVarValues,
  33. useInvalidateSysVarValues,
  34. useResetConversationVar,
  35. useResetToLastRunValue,
  36. useDeleteAllInspectorVars,
  37. useDeleteNodeInspectorVars,
  38. useDeleteInspectVar,
  39. useEditInspectorVar,
  40. } = useFLow({ flowType })
  41. const invalidateConversationVarValues = useInvalidateConversationVarValues(flowId)
  42. const { mutateAsync: doResetConversationVar } = useResetConversationVar(flowId)
  43. const { mutateAsync: doResetToLastRunValue } = useResetToLastRunValue(flowId)
  44. const invalidateSysVarValues = useInvalidateSysVarValues(flowId)
  45. const { mutateAsync: doDeleteAllInspectorVars } = useDeleteAllInspectorVars(flowId)
  46. const { mutate: doDeleteNodeInspectorVars } = useDeleteNodeInspectorVars(flowId)
  47. const { mutate: doDeleteInspectVar } = useDeleteInspectVar(flowId)
  48. const { mutateAsync: doEditInspectorVar } = useEditInspectorVar(flowId)
  49. const { handleCancelNodeSuccessStatus } = useNodesInteractionsWithoutSync()
  50. const { handleEdgeCancelRunningStatus } = useEdgesInteractionsWithoutSync()
  51. const getNodeInspectVars = useCallback((nodeId: string) => {
  52. const { nodesWithInspectVars } = workflowStore.getState()
  53. const node = nodesWithInspectVars.find(node => node.nodeId === nodeId)
  54. return node
  55. }, [workflowStore])
  56. const getVarId = useCallback((nodeId: string, varName: string) => {
  57. const node = getNodeInspectVars(nodeId)
  58. if (!node)
  59. return undefined
  60. const varId = node.vars.find((varItem) => {
  61. return varItem.selector[1] === varName
  62. })?.id
  63. return varId
  64. }, [getNodeInspectVars])
  65. const getInspectVar = useCallback((nodeId: string, name: string): VarInInspect | undefined => {
  66. const node = getNodeInspectVars(nodeId)
  67. if (!node)
  68. return undefined
  69. const variable = node.vars.find((varItem) => {
  70. return varItem.name === name
  71. })
  72. return variable
  73. }, [getNodeInspectVars])
  74. const hasSetInspectVar = useCallback((nodeId: string, name: string, sysVars: VarInInspect[], conversationVars: VarInInspect[]) => {
  75. const isEnv = isENV([nodeId])
  76. if (isEnv) // always have value
  77. return true
  78. const isSys = isSystemVar([nodeId])
  79. if (isSys)
  80. return sysVars.some(varItem => varItem.selector?.[1]?.replace('sys.', '') === name)
  81. const isChatVar = isConversationVar([nodeId])
  82. if (isChatVar)
  83. return conversationVars.some(varItem => varItem.selector?.[1] === name)
  84. return getInspectVar(nodeId, name) !== undefined
  85. }, [getInspectVar])
  86. const hasNodeInspectVars = useCallback((nodeId: string) => {
  87. return !!getNodeInspectVars(nodeId)
  88. }, [getNodeInspectVars])
  89. const fetchInspectVarValue = useCallback(async (selector: ValueSelector, schemaTypeDefinitions: SchemaTypeDefinition[]) => {
  90. const {
  91. setNodeInspectVars,
  92. buildInTools,
  93. customTools,
  94. workflowTools,
  95. mcpTools,
  96. dataSourceList,
  97. } = workflowStore.getState()
  98. const nodeId = selector[0]
  99. const isSystemVar = nodeId === 'sys'
  100. const isConversationVar = nodeId === 'conversation'
  101. if (isSystemVar) {
  102. invalidateSysVarValues()
  103. return
  104. }
  105. if (isConversationVar) {
  106. invalidateConversationVarValues()
  107. return
  108. }
  109. const { getNodes } = store.getState()
  110. const nodeArr = getNodes()
  111. const currentNode = nodeArr.find(node => node.id === nodeId)
  112. const allPluginInfoList = {
  113. buildInTools,
  114. customTools,
  115. workflowTools,
  116. mcpTools,
  117. dataSourceList: dataSourceList ?? [],
  118. }
  119. const currentNodeOutputVars = toNodeOutputVars([currentNode], false, () => true, [], [], [], allPluginInfoList, schemaTypeDefinitions)
  120. const vars = await fetchNodeInspectVars(flowType, flowId, nodeId)
  121. const varsWithSchemaType = vars.map((varItem) => {
  122. const schemaType = currentNodeOutputVars[0]?.vars.find(v => v.variable === varItem.name)?.schemaType || ''
  123. return {
  124. ...varItem,
  125. schemaType,
  126. }
  127. })
  128. setNodeInspectVars(nodeId, varsWithSchemaType)
  129. }, [workflowStore, flowType, flowId, invalidateSysVarValues, invalidateConversationVarValues])
  130. // after last run would call this
  131. const appendNodeInspectVars = useCallback((nodeId: string, payload: VarInInspect[], allNodes: Node[]) => {
  132. const {
  133. nodesWithInspectVars,
  134. setNodesWithInspectVars,
  135. } = workflowStore.getState()
  136. const nodes = produce(nodesWithInspectVars, (draft) => {
  137. const nodeInfo = allNodes.find(node => node.id === nodeId)
  138. if (nodeInfo) {
  139. const index = draft.findIndex(node => node.nodeId === nodeId)
  140. if (index === -1) {
  141. draft.unshift({
  142. nodeId,
  143. nodeType: nodeInfo.data.type,
  144. title: nodeInfo.data.title,
  145. vars: payload,
  146. nodePayload: nodeInfo.data,
  147. })
  148. }
  149. else {
  150. draft[index].vars = payload
  151. // put the node to the topAdd commentMore actions
  152. draft.unshift(draft.splice(index, 1)[0])
  153. }
  154. }
  155. })
  156. setNodesWithInspectVars(nodes)
  157. handleCancelNodeSuccessStatus(nodeId)
  158. }, [workflowStore, handleCancelNodeSuccessStatus])
  159. const hasNodeInspectVar = useCallback((nodeId: string, varId: string) => {
  160. const { nodesWithInspectVars } = workflowStore.getState()
  161. const targetNode = nodesWithInspectVars.find(item => item.nodeId === nodeId)
  162. if (!targetNode || !targetNode.vars)
  163. return false
  164. return targetNode.vars.some(item => item.id === varId)
  165. }, [workflowStore])
  166. const deleteInspectVar = useCallback(async (nodeId: string, varId: string) => {
  167. const { deleteInspectVar } = workflowStore.getState()
  168. if (hasNodeInspectVar(nodeId, varId)) {
  169. await doDeleteInspectVar(varId)
  170. deleteInspectVar(nodeId, varId)
  171. }
  172. }, [doDeleteInspectVar, workflowStore, hasNodeInspectVar])
  173. const resetConversationVar = useCallback(async (varId: string) => {
  174. await doResetConversationVar(varId)
  175. invalidateConversationVarValues()
  176. }, [doResetConversationVar, invalidateConversationVarValues])
  177. const deleteNodeInspectorVars = useCallback(async (nodeId: string) => {
  178. const { deleteNodeInspectVars } = workflowStore.getState()
  179. if (hasNodeInspectVars(nodeId)) {
  180. await doDeleteNodeInspectorVars(nodeId)
  181. deleteNodeInspectVars(nodeId)
  182. }
  183. }, [doDeleteNodeInspectorVars, workflowStore, hasNodeInspectVars])
  184. const deleteAllInspectorVars = useCallback(async () => {
  185. const { deleteAllInspectVars } = workflowStore.getState()
  186. await doDeleteAllInspectorVars()
  187. await invalidateConversationVarValues()
  188. await invalidateSysVarValues()
  189. deleteAllInspectVars()
  190. handleEdgeCancelRunningStatus()
  191. }, [doDeleteAllInspectorVars, invalidateConversationVarValues, invalidateSysVarValues, workflowStore, handleEdgeCancelRunningStatus])
  192. const editInspectVarValue = useCallback(async (nodeId: string, varId: string, value: any) => {
  193. const { setInspectVarValue } = workflowStore.getState()
  194. await doEditInspectorVar({
  195. varId,
  196. value,
  197. })
  198. setInspectVarValue(nodeId, varId, value)
  199. if (nodeId === VarInInspectType.conversation)
  200. invalidateConversationVarValues()
  201. if (nodeId === VarInInspectType.system)
  202. invalidateSysVarValues()
  203. }, [doEditInspectorVar, invalidateConversationVarValues, invalidateSysVarValues, workflowStore])
  204. const renameInspectVarName = useCallback(async (nodeId: string, oldName: string, newName: string) => {
  205. const { renameInspectVarName } = workflowStore.getState()
  206. const varId = getVarId(nodeId, oldName)
  207. if (!varId)
  208. return
  209. const newSelector = [nodeId, newName]
  210. await doEditInspectorVar({
  211. varId,
  212. name: newName,
  213. })
  214. renameInspectVarName(nodeId, varId, newSelector)
  215. }, [doEditInspectorVar, getVarId, workflowStore])
  216. const isInspectVarEdited = useCallback((nodeId: string, name: string) => {
  217. const inspectVar = getInspectVar(nodeId, name)
  218. if (!inspectVar)
  219. return false
  220. return inspectVar.edited
  221. }, [getInspectVar])
  222. const resetToLastRunVar = useCallback(async (nodeId: string, varId: string) => {
  223. const { resetToLastRunVar } = workflowStore.getState()
  224. const isSysVar = nodeId === 'sys'
  225. const data = await doResetToLastRunValue(varId)
  226. if (isSysVar)
  227. invalidateSysVarValues()
  228. else
  229. resetToLastRunVar(nodeId, varId, data.value)
  230. }, [doResetToLastRunValue, invalidateSysVarValues, workflowStore])
  231. return {
  232. hasNodeInspectVars,
  233. hasSetInspectVar,
  234. fetchInspectVarValue,
  235. editInspectVarValue,
  236. renameInspectVarName,
  237. appendNodeInspectVars,
  238. deleteInspectVar,
  239. deleteNodeInspectorVars,
  240. deleteAllInspectorVars,
  241. isInspectVarEdited,
  242. resetToLastRunVar,
  243. invalidateSysVarValues,
  244. resetConversationVar,
  245. invalidateConversationVarValues,
  246. }
  247. }