You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

use-inspect-vars-crud.ts 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. import { fetchNodeInspectVars } from '@/service/workflow'
  2. import { useStore, useWorkflowStore } from '../store'
  3. import type { ValueSelector } from '../types'
  4. import type { VarInInspect } from '@/types/workflow'
  5. import { VarInInspectType } from '@/types/workflow'
  6. import {
  7. useConversationVarValues,
  8. useDeleteAllInspectorVars,
  9. useDeleteInspectVar,
  10. useDeleteNodeInspectorVars,
  11. useEditInspectorVar,
  12. useInvalidateConversationVarValues,
  13. useInvalidateSysVarValues,
  14. useLastRun,
  15. useResetConversationVar,
  16. useResetToLastRunValue,
  17. useSysVarValues,
  18. } from '@/service/use-workflow'
  19. import { useCallback, useEffect, useState } from 'react'
  20. import { isConversationVar, isENV, isSystemVar } from '../nodes/_base/components/variable/utils'
  21. import produce from 'immer'
  22. import type { Node } from '@/app/components/workflow/types'
  23. import { useNodesInteractionsWithoutSync } from './use-nodes-interactions-without-sync'
  24. import { useEdgesInteractionsWithoutSync } from './use-edges-interactions-without-sync'
  25. const useInspectVarsCrud = () => {
  26. const workflowStore = useWorkflowStore()
  27. const nodesWithInspectVars = useStore(s => s.nodesWithInspectVars)
  28. const {
  29. appId,
  30. setNodeInspectVars,
  31. setInspectVarValue,
  32. renameInspectVarName: renameInspectVarNameInStore,
  33. deleteAllInspectVars: deleteAllInspectVarsInStore,
  34. deleteNodeInspectVars: deleteNodeInspectVarsInStore,
  35. deleteInspectVar: deleteInspectVarInStore,
  36. setNodesWithInspectVars,
  37. resetToLastRunVar: resetToLastRunVarInStore,
  38. } = workflowStore.getState()
  39. const { data: conversationVars } = useConversationVarValues(appId)
  40. const invalidateConversationVarValues = useInvalidateConversationVarValues(appId)
  41. const { mutateAsync: doResetConversationVar } = useResetConversationVar(appId)
  42. const { mutateAsync: doResetToLastRunValue } = useResetToLastRunValue(appId)
  43. const { data: systemVars } = useSysVarValues(appId)
  44. const invalidateSysVarValues = useInvalidateSysVarValues(appId)
  45. const { mutateAsync: doDeleteAllInspectorVars } = useDeleteAllInspectorVars(appId)
  46. const { mutate: doDeleteNodeInspectorVars } = useDeleteNodeInspectorVars(appId)
  47. const { mutate: doDeleteInspectVar } = useDeleteInspectVar(appId)
  48. const { mutateAsync: doEditInspectorVar } = useEditInspectorVar(appId)
  49. const { handleCancelNodeSuccessStatus } = useNodesInteractionsWithoutSync()
  50. const { handleEdgeCancelRunningStatus } = useEdgesInteractionsWithoutSync()
  51. const getNodeInspectVars = useCallback((nodeId: string) => {
  52. const node = nodesWithInspectVars.find(node => node.nodeId === nodeId)
  53. return node
  54. }, [nodesWithInspectVars])
  55. const getVarId = useCallback((nodeId: string, varName: string) => {
  56. const node = getNodeInspectVars(nodeId)
  57. if (!node)
  58. return undefined
  59. const varId = node.vars.find((varItem) => {
  60. return varItem.selector[1] === varName
  61. })?.id
  62. return varId
  63. }, [getNodeInspectVars])
  64. const getInspectVar = useCallback((nodeId: string, name: string): VarInInspect | undefined => {
  65. const node = getNodeInspectVars(nodeId)
  66. if (!node)
  67. return undefined
  68. const variable = node.vars.find((varItem) => {
  69. return varItem.name === name
  70. })
  71. return variable
  72. }, [getNodeInspectVars])
  73. const hasSetInspectVar = useCallback((nodeId: string, name: string, sysVars: VarInInspect[], conversationVars: VarInInspect[]) => {
  74. const isEnv = isENV([nodeId])
  75. if (isEnv) // always have value
  76. return true
  77. const isSys = isSystemVar([nodeId])
  78. if (isSys)
  79. return sysVars.some(varItem => varItem.selector?.[1]?.replace('sys.', '') === name)
  80. const isChatVar = isConversationVar([nodeId])
  81. if (isChatVar)
  82. return conversationVars.some(varItem => varItem.selector?.[1] === name)
  83. return getInspectVar(nodeId, name) !== undefined
  84. }, [getInspectVar])
  85. const hasNodeInspectVars = useCallback((nodeId: string) => {
  86. return !!getNodeInspectVars(nodeId)
  87. }, [getNodeInspectVars])
  88. const fetchInspectVarValue = async (selector: ValueSelector) => {
  89. const nodeId = selector[0]
  90. const isSystemVar = nodeId === 'sys'
  91. const isConversationVar = nodeId === 'conversation'
  92. if (isSystemVar) {
  93. invalidateSysVarValues()
  94. return
  95. }
  96. if (isConversationVar) {
  97. invalidateConversationVarValues()
  98. return
  99. }
  100. const vars = await fetchNodeInspectVars(appId, nodeId)
  101. setNodeInspectVars(nodeId, vars)
  102. }
  103. // after last run would call this
  104. const appendNodeInspectVars = (nodeId: string, payload: VarInInspect[], allNodes: Node[]) => {
  105. const nodes = produce(nodesWithInspectVars, (draft) => {
  106. const nodeInfo = allNodes.find(node => node.id === nodeId)
  107. if (nodeInfo) {
  108. const index = draft.findIndex(node => node.nodeId === nodeId)
  109. if (index === -1) {
  110. draft.push({
  111. nodeId,
  112. nodeType: nodeInfo.data.type,
  113. title: nodeInfo.data.title,
  114. vars: payload,
  115. })
  116. }
  117. else {
  118. draft[index].vars = payload
  119. }
  120. }
  121. })
  122. setNodesWithInspectVars(nodes)
  123. handleCancelNodeSuccessStatus(nodeId)
  124. }
  125. const hasNodeInspectVar = (nodeId: string, varId: string) => {
  126. const targetNode = nodesWithInspectVars.find(item => item.nodeId === nodeId)
  127. if(!targetNode || !targetNode.vars)
  128. return false
  129. return targetNode.vars.some(item => item.id === varId)
  130. }
  131. const deleteInspectVar = async (nodeId: string, varId: string) => {
  132. if(hasNodeInspectVar(nodeId, varId)) {
  133. await doDeleteInspectVar(varId)
  134. deleteInspectVarInStore(nodeId, varId)
  135. }
  136. }
  137. const resetConversationVar = async (varId: string) => {
  138. await doResetConversationVar(varId)
  139. invalidateConversationVarValues()
  140. }
  141. const deleteNodeInspectorVars = async (nodeId: string) => {
  142. if (hasNodeInspectVars(nodeId)) {
  143. await doDeleteNodeInspectorVars(nodeId)
  144. deleteNodeInspectVarsInStore(nodeId)
  145. }
  146. }
  147. const deleteAllInspectorVars = async () => {
  148. await doDeleteAllInspectorVars()
  149. await invalidateConversationVarValues()
  150. await invalidateSysVarValues()
  151. deleteAllInspectVarsInStore()
  152. handleEdgeCancelRunningStatus()
  153. }
  154. const editInspectVarValue = useCallback(async (nodeId: string, varId: string, value: any) => {
  155. await doEditInspectorVar({
  156. varId,
  157. value,
  158. })
  159. setInspectVarValue(nodeId, varId, value)
  160. if (nodeId === VarInInspectType.conversation)
  161. invalidateConversationVarValues()
  162. if (nodeId === VarInInspectType.system)
  163. invalidateSysVarValues()
  164. }, [doEditInspectorVar, invalidateConversationVarValues, invalidateSysVarValues, setInspectVarValue])
  165. const [currNodeId, setCurrNodeId] = useState<string | null>(null)
  166. const [currEditVarId, setCurrEditVarId] = useState<string | null>(null)
  167. const { data } = useLastRun(appId, currNodeId || '', !!currNodeId)
  168. useEffect(() => {
  169. if (data && currNodeId && currEditVarId) {
  170. const inspectVar = getNodeInspectVars(currNodeId)?.vars?.find(item => item.id === currEditVarId)
  171. resetToLastRunVarInStore(currNodeId, currEditVarId, data.outputs?.[inspectVar?.selector?.[1] || ''])
  172. }
  173. }, [data, currNodeId, currEditVarId, getNodeInspectVars, editInspectVarValue, resetToLastRunVarInStore])
  174. const renameInspectVarName = async (nodeId: string, oldName: string, newName: string) => {
  175. const varId = getVarId(nodeId, oldName)
  176. if (!varId)
  177. return
  178. const newSelector = [nodeId, newName]
  179. await doEditInspectorVar({
  180. varId,
  181. name: newName,
  182. })
  183. renameInspectVarNameInStore(nodeId, varId, newSelector)
  184. }
  185. const isInspectVarEdited = useCallback((nodeId: string, name: string) => {
  186. const inspectVar = getInspectVar(nodeId, name)
  187. if (!inspectVar)
  188. return false
  189. return inspectVar.edited
  190. }, [getInspectVar])
  191. const resetToLastRunVar = async (nodeId: string, varId: string) => {
  192. await doResetToLastRunValue(varId)
  193. setCurrNodeId(nodeId)
  194. setCurrEditVarId(varId)
  195. }
  196. return {
  197. conversationVars: conversationVars || [],
  198. systemVars: systemVars || [],
  199. nodesWithInspectVars,
  200. hasNodeInspectVars,
  201. hasSetInspectVar,
  202. fetchInspectVarValue,
  203. editInspectVarValue,
  204. renameInspectVarName,
  205. appendNodeInspectVars,
  206. deleteInspectVar,
  207. deleteNodeInspectorVars,
  208. deleteAllInspectorVars,
  209. isInspectVarEdited,
  210. resetToLastRunVar,
  211. invalidateSysVarValues,
  212. resetConversationVar,
  213. invalidateConversationVarValues,
  214. }
  215. }
  216. export default useInspectVarsCrud