hooks.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import { useCallback } from 'react'
  2. import {
  3. useNodes,
  4. useStoreApi,
  5. } from 'reactflow'
  6. import { uniqBy } from 'lodash-es'
  7. import produce from 'immer'
  8. import {
  9. useIsChatMode,
  10. useNodeDataUpdate,
  11. useWorkflow,
  12. useWorkflowVariables,
  13. } from '../../hooks'
  14. import type {
  15. Node,
  16. ValueSelector,
  17. Var,
  18. } from '../../types'
  19. import { useWorkflowStore } from '../../store'
  20. import type {
  21. VarGroupItem,
  22. VariableAssignerNodeType,
  23. } from './types'
  24. export const useVariableAssigner = () => {
  25. const store = useStoreApi()
  26. const workflowStore = useWorkflowStore()
  27. const { handleNodeDataUpdate } = useNodeDataUpdate()
  28. const handleAssignVariableValueChange = useCallback((nodeId: string, value: ValueSelector, varDetail: Var, groupId?: string) => {
  29. const { getNodes } = store.getState()
  30. const nodes = getNodes()
  31. const node: Node<VariableAssignerNodeType> = nodes.find(node => node.id === nodeId)!
  32. let payload
  33. if (groupId && groupId !== 'target') {
  34. payload = {
  35. advanced_settings: {
  36. ...node.data.advanced_settings,
  37. groups: node.data.advanced_settings?.groups.map((group: VarGroupItem & { groupId: string }) => {
  38. if (group.groupId === groupId && !group.variables.some(item => item.join('.') === (value as ValueSelector).join('.'))) {
  39. return {
  40. ...group,
  41. variables: [...group.variables, value],
  42. output_type: varDetail.type,
  43. }
  44. }
  45. return group
  46. }),
  47. },
  48. }
  49. }
  50. else {
  51. if (node.data.variables.some(item => item.join('.') === (value as ValueSelector).join('.')))
  52. return
  53. payload = {
  54. variables: [...node.data.variables, value],
  55. output_type: varDetail.type,
  56. }
  57. }
  58. handleNodeDataUpdate({
  59. id: nodeId,
  60. data: payload,
  61. })
  62. }, [store, handleNodeDataUpdate])
  63. const handleAddVariableInAddVariablePopupWithPosition = useCallback((
  64. nodeId: string,
  65. variableAssignerNodeId: string,
  66. variableAssignerNodeHandleId: string,
  67. value: ValueSelector,
  68. varDetail: Var,
  69. ) => {
  70. const {
  71. getNodes,
  72. setNodes,
  73. } = store.getState()
  74. const {
  75. setShowAssignVariablePopup,
  76. } = workflowStore.getState()
  77. const newNodes = produce(getNodes(), (draft) => {
  78. draft.forEach((node) => {
  79. if (node.id === nodeId || node.id === variableAssignerNodeId) {
  80. node.data = {
  81. ...node.data,
  82. _showAddVariablePopup: false,
  83. _holdAddVariablePopup: false,
  84. }
  85. }
  86. })
  87. })
  88. setNodes(newNodes)
  89. setShowAssignVariablePopup(undefined)
  90. handleAssignVariableValueChange(variableAssignerNodeId, value, varDetail, variableAssignerNodeHandleId)
  91. }, [store, workflowStore, handleAssignVariableValueChange])
  92. const handleGroupItemMouseEnter = useCallback((groupId: string) => {
  93. const {
  94. setHoveringAssignVariableGroupId,
  95. } = workflowStore.getState()
  96. setHoveringAssignVariableGroupId(groupId)
  97. }, [workflowStore])
  98. const handleGroupItemMouseLeave = useCallback(() => {
  99. const {
  100. connectingNodePayload,
  101. setHoveringAssignVariableGroupId,
  102. } = workflowStore.getState()
  103. if (connectingNodePayload)
  104. setHoveringAssignVariableGroupId(undefined)
  105. }, [workflowStore])
  106. return {
  107. handleAddVariableInAddVariablePopupWithPosition,
  108. handleGroupItemMouseEnter,
  109. handleGroupItemMouseLeave,
  110. handleAssignVariableValueChange,
  111. }
  112. }
  113. export const useGetAvailableVars = () => {
  114. const nodes: Node[] = useNodes()
  115. const { getBeforeNodesInSameBranchIncludeParent } = useWorkflow()
  116. const { getNodeAvailableVars } = useWorkflowVariables()
  117. const isChatMode = useIsChatMode()
  118. const getAvailableVars = useCallback((nodeId: string, handleId: string, filterVar: (v: Var) => boolean, hideEnv = false) => {
  119. const availableNodes: Node[] = []
  120. const currentNode = nodes.find(node => node.id === nodeId)!
  121. if (!currentNode)
  122. return []
  123. const beforeNodes = getBeforeNodesInSameBranchIncludeParent(nodeId)
  124. availableNodes.push(...beforeNodes)
  125. const parentNode = nodes.find(node => node.id === currentNode.parentId)
  126. if (hideEnv) {
  127. return getNodeAvailableVars({
  128. parentNode,
  129. beforeNodes: uniqBy(availableNodes, 'id').filter(node => node.id !== nodeId),
  130. isChatMode,
  131. hideEnv,
  132. hideChatVar: hideEnv,
  133. filterVar,
  134. })
  135. .map(node => ({
  136. ...node,
  137. vars: node.isStartNode ? node.vars.filter(v => !v.variable.startsWith('sys.')) : node.vars,
  138. }))
  139. .filter(item => item.vars.length > 0)
  140. }
  141. return getNodeAvailableVars({
  142. parentNode,
  143. beforeNodes: uniqBy(availableNodes, 'id').filter(node => node.id !== nodeId),
  144. isChatMode,
  145. filterVar,
  146. })
  147. }, [nodes, getBeforeNodesInSameBranchIncludeParent, getNodeAvailableVars, isChatMode])
  148. return getAvailableVars
  149. }