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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. import {
  2. useCallback,
  3. useRef,
  4. } from 'react'
  5. import produce from 'immer'
  6. import { v4 as uuid4 } from 'uuid'
  7. import {
  8. useIsChatMode,
  9. useIsNodeInLoop,
  10. useNodesReadOnly,
  11. useWorkflow,
  12. } from '../../hooks'
  13. import { ValueType, VarType } from '../../types'
  14. import type { ErrorHandleMode, Var } from '../../types'
  15. import useNodeCrud from '../_base/hooks/use-node-crud'
  16. import { toNodeOutputVars } from '../_base/components/variable/utils'
  17. import { getOperators } from './utils'
  18. import { LogicalOperator } from './types'
  19. import type { HandleAddCondition, HandleAddSubVariableCondition, HandleRemoveCondition, HandleToggleConditionLogicalOperator, HandleToggleSubVariableConditionLogicalOperator, HandleUpdateCondition, HandleUpdateSubVariableCondition, LoopNodeType } from './types'
  20. import useIsVarFileAttribute from './use-is-var-file-attribute'
  21. import { useStore } from '@/app/components/workflow/store'
  22. const DELIMITER = '@@@@@'
  23. const useConfig = (id: string, payload: LoopNodeType) => {
  24. const { nodesReadOnly: readOnly } = useNodesReadOnly()
  25. const { isNodeInLoop } = useIsNodeInLoop(id)
  26. const isChatMode = useIsChatMode()
  27. const conversationVariables = useStore(s => s.conversationVariables)
  28. const { inputs, setInputs } = useNodeCrud<LoopNodeType>(id, payload)
  29. const inputsRef = useRef(inputs)
  30. const handleInputsChange = useCallback((newInputs: LoopNodeType) => {
  31. inputsRef.current = newInputs
  32. setInputs(newInputs)
  33. }, [setInputs])
  34. const filterInputVar = useCallback((varPayload: Var) => {
  35. return [VarType.array, VarType.arrayString, VarType.arrayNumber, VarType.arrayObject, VarType.arrayFile].includes(varPayload.type)
  36. }, [])
  37. // output
  38. const { getLoopNodeChildren, getBeforeNodesInSameBranch } = useWorkflow()
  39. const beforeNodes = getBeforeNodesInSameBranch(id)
  40. const loopChildrenNodes = [{ id, data: payload } as any, ...getLoopNodeChildren(id)]
  41. const canChooseVarNodes = [...beforeNodes, ...loopChildrenNodes]
  42. const childrenNodeVars = toNodeOutputVars(loopChildrenNodes, isChatMode, undefined, [], conversationVariables)
  43. const {
  44. getIsVarFileAttribute,
  45. } = useIsVarFileAttribute({
  46. nodeId: id,
  47. })
  48. const changeErrorResponseMode = useCallback((item: { value: unknown }) => {
  49. const newInputs = produce(inputs, (draft) => {
  50. draft.error_handle_mode = item.value as ErrorHandleMode
  51. })
  52. setInputs(newInputs)
  53. }, [inputs, setInputs])
  54. const handleAddCondition = useCallback<HandleAddCondition>((valueSelector, varItem) => {
  55. const newInputs = produce(inputs, (draft) => {
  56. if (!draft.break_conditions)
  57. draft.break_conditions = []
  58. draft.break_conditions?.push({
  59. id: uuid4(),
  60. varType: varItem.type,
  61. variable_selector: valueSelector,
  62. comparison_operator: getOperators(varItem.type, getIsVarFileAttribute(valueSelector) ? { key: valueSelector.slice(-1)[0] } : undefined)[0],
  63. value: '',
  64. })
  65. })
  66. setInputs(newInputs)
  67. }, [getIsVarFileAttribute, inputs, setInputs])
  68. const handleRemoveCondition = useCallback<HandleRemoveCondition>((conditionId) => {
  69. const newInputs = produce(inputs, (draft) => {
  70. draft.break_conditions = draft.break_conditions?.filter(item => item.id !== conditionId)
  71. })
  72. setInputs(newInputs)
  73. }, [inputs, setInputs])
  74. const handleUpdateCondition = useCallback<HandleUpdateCondition>((conditionId, newCondition) => {
  75. const newInputs = produce(inputs, (draft) => {
  76. const targetCondition = draft.break_conditions?.find(item => item.id === conditionId)
  77. if (targetCondition)
  78. Object.assign(targetCondition, newCondition)
  79. })
  80. setInputs(newInputs)
  81. }, [inputs, setInputs])
  82. const handleToggleConditionLogicalOperator = useCallback<HandleToggleConditionLogicalOperator>(() => {
  83. const newInputs = produce(inputs, (draft) => {
  84. draft.logical_operator = draft.logical_operator === LogicalOperator.and ? LogicalOperator.or : LogicalOperator.and
  85. })
  86. setInputs(newInputs)
  87. }, [inputs, setInputs])
  88. const handleAddSubVariableCondition = useCallback<HandleAddSubVariableCondition>((conditionId: string, key?: string) => {
  89. const newInputs = produce(inputs, (draft) => {
  90. const condition = draft.break_conditions?.find(item => item.id === conditionId)
  91. if (!condition)
  92. return
  93. if (!condition?.sub_variable_condition) {
  94. condition.sub_variable_condition = {
  95. logical_operator: LogicalOperator.and,
  96. conditions: [],
  97. }
  98. }
  99. const subVarCondition = condition.sub_variable_condition
  100. if (subVarCondition) {
  101. if (!subVarCondition.conditions)
  102. subVarCondition.conditions = []
  103. const svcComparisonOperators = getOperators(VarType.string, { key: key || '' })
  104. subVarCondition.conditions.push({
  105. id: uuid4(),
  106. key: key || '',
  107. varType: VarType.string,
  108. comparison_operator: (svcComparisonOperators && svcComparisonOperators.length) ? svcComparisonOperators[0] : undefined,
  109. value: '',
  110. })
  111. }
  112. })
  113. setInputs(newInputs)
  114. }, [inputs, setInputs])
  115. const handleRemoveSubVariableCondition = useCallback((conditionId: string, subConditionId: string) => {
  116. const newInputs = produce(inputs, (draft) => {
  117. const condition = draft.break_conditions?.find(item => item.id === conditionId)
  118. if (!condition)
  119. return
  120. if (!condition?.sub_variable_condition)
  121. return
  122. const subVarCondition = condition.sub_variable_condition
  123. if (subVarCondition)
  124. subVarCondition.conditions = subVarCondition.conditions.filter(item => item.id !== subConditionId)
  125. })
  126. setInputs(newInputs)
  127. }, [inputs, setInputs])
  128. const handleUpdateSubVariableCondition = useCallback<HandleUpdateSubVariableCondition>((conditionId, subConditionId, newSubCondition) => {
  129. const newInputs = produce(inputs, (draft) => {
  130. const targetCondition = draft.break_conditions?.find(item => item.id === conditionId)
  131. if (targetCondition && targetCondition.sub_variable_condition) {
  132. const targetSubCondition = targetCondition.sub_variable_condition.conditions.find(item => item.id === subConditionId)
  133. if (targetSubCondition)
  134. Object.assign(targetSubCondition, newSubCondition)
  135. }
  136. })
  137. setInputs(newInputs)
  138. }, [inputs, setInputs])
  139. const handleToggleSubVariableConditionLogicalOperator = useCallback<HandleToggleSubVariableConditionLogicalOperator>((conditionId) => {
  140. const newInputs = produce(inputs, (draft) => {
  141. const targetCondition = draft.break_conditions?.find(item => item.id === conditionId)
  142. if (targetCondition && targetCondition.sub_variable_condition)
  143. targetCondition.sub_variable_condition.logical_operator = targetCondition.sub_variable_condition.logical_operator === LogicalOperator.and ? LogicalOperator.or : LogicalOperator.and
  144. })
  145. setInputs(newInputs)
  146. }, [inputs, setInputs])
  147. const handleUpdateLoopCount = useCallback((value: number) => {
  148. const newInputs = produce(inputs, (draft) => {
  149. draft.loop_count = value
  150. })
  151. setInputs(newInputs)
  152. }, [inputs, setInputs])
  153. const handleAddLoopVariable = useCallback(() => {
  154. const newInputs = produce(inputsRef.current, (draft) => {
  155. if (!draft.loop_variables)
  156. draft.loop_variables = []
  157. draft.loop_variables.push({
  158. id: uuid4(),
  159. label: '',
  160. var_type: VarType.string,
  161. value_type: ValueType.constant,
  162. value: '',
  163. })
  164. })
  165. handleInputsChange(newInputs)
  166. }, [handleInputsChange])
  167. const handleRemoveLoopVariable = useCallback((id: string) => {
  168. const newInputs = produce(inputsRef.current, (draft) => {
  169. draft.loop_variables = draft.loop_variables?.filter(item => item.id !== id)
  170. })
  171. handleInputsChange(newInputs)
  172. }, [handleInputsChange])
  173. const handleUpdateLoopVariable = useCallback((id: string, updateData: any) => {
  174. const loopVariables = inputsRef.current.loop_variables || []
  175. const index = loopVariables.findIndex(item => item.id === id)
  176. const newInputs = produce(inputsRef.current, (draft) => {
  177. if (index > -1) {
  178. draft.loop_variables![index] = {
  179. ...draft.loop_variables![index],
  180. ...updateData,
  181. }
  182. }
  183. })
  184. handleInputsChange(newInputs)
  185. }, [handleInputsChange])
  186. return {
  187. readOnly,
  188. inputs,
  189. filterInputVar,
  190. childrenNodeVars,
  191. loopChildrenNodes,
  192. handleAddCondition,
  193. handleRemoveCondition,
  194. handleUpdateCondition,
  195. handleToggleConditionLogicalOperator,
  196. handleAddSubVariableCondition,
  197. handleUpdateSubVariableCondition,
  198. handleRemoveSubVariableCondition,
  199. handleToggleSubVariableConditionLogicalOperator,
  200. handleUpdateLoopCount,
  201. changeErrorResponseMode,
  202. handleAddLoopVariable,
  203. handleRemoveLoopVariable,
  204. handleUpdateLoopVariable,
  205. }
  206. }
  207. export default useConfig