Co-authored-by: Joel <iamjoel007@gmail.com>tags/1.6.0
| import type { WorkflowProps } from '@/app/components/workflow' | import type { WorkflowProps } from '@/app/components/workflow' | ||||
| import WorkflowChildren from './workflow-children' | import WorkflowChildren from './workflow-children' | ||||
| import { | import { | ||||
| useConfigsMap, | |||||
| useInspectVarsCrud, | |||||
| useNodesSyncDraft, | useNodesSyncDraft, | ||||
| useSetWorkflowVarsWithValue, | |||||
| useWorkflowRefreshDraft, | useWorkflowRefreshDraft, | ||||
| useWorkflowRun, | useWorkflowRun, | ||||
| useWorkflowStartRun, | useWorkflowStartRun, | ||||
| handleWorkflowStartRunInChatflow, | handleWorkflowStartRunInChatflow, | ||||
| handleWorkflowStartRunInWorkflow, | handleWorkflowStartRunInWorkflow, | ||||
| } = useWorkflowStartRun() | } = useWorkflowStartRun() | ||||
| const { fetchInspectVars } = useSetWorkflowVarsWithValue() | |||||
| const { | |||||
| hasNodeInspectVars, | |||||
| hasSetInspectVar, | |||||
| fetchInspectVarValue, | |||||
| editInspectVarValue, | |||||
| renameInspectVarName, | |||||
| appendNodeInspectVars, | |||||
| deleteInspectVar, | |||||
| deleteNodeInspectorVars, | |||||
| deleteAllInspectorVars, | |||||
| isInspectVarEdited, | |||||
| resetToLastRunVar, | |||||
| invalidateSysVarValues, | |||||
| resetConversationVar, | |||||
| invalidateConversationVarValues, | |||||
| } = useInspectVarsCrud() | |||||
| const configsMap = useConfigsMap() | |||||
| const hooksStore = useMemo(() => { | const hooksStore = useMemo(() => { | ||||
| return { | return { | ||||
| handleStartWorkflowRun, | handleStartWorkflowRun, | ||||
| handleWorkflowStartRunInChatflow, | handleWorkflowStartRunInChatflow, | ||||
| handleWorkflowStartRunInWorkflow, | handleWorkflowStartRunInWorkflow, | ||||
| fetchInspectVars, | |||||
| hasNodeInspectVars, | |||||
| hasSetInspectVar, | |||||
| fetchInspectVarValue, | |||||
| editInspectVarValue, | |||||
| renameInspectVarName, | |||||
| appendNodeInspectVars, | |||||
| deleteInspectVar, | |||||
| deleteNodeInspectorVars, | |||||
| deleteAllInspectorVars, | |||||
| isInspectVarEdited, | |||||
| resetToLastRunVar, | |||||
| invalidateSysVarValues, | |||||
| resetConversationVar, | |||||
| invalidateConversationVarValues, | |||||
| configsMap, | |||||
| } | } | ||||
| }, [ | }, [ | ||||
| syncWorkflowDraftWhenPageClose, | syncWorkflowDraftWhenPageClose, | ||||
| handleStartWorkflowRun, | handleStartWorkflowRun, | ||||
| handleWorkflowStartRunInChatflow, | handleWorkflowStartRunInChatflow, | ||||
| handleWorkflowStartRunInWorkflow, | handleWorkflowStartRunInWorkflow, | ||||
| fetchInspectVars, | |||||
| hasNodeInspectVars, | |||||
| hasSetInspectVar, | |||||
| fetchInspectVarValue, | |||||
| editInspectVarValue, | |||||
| renameInspectVarName, | |||||
| appendNodeInspectVars, | |||||
| deleteInspectVar, | |||||
| deleteNodeInspectorVars, | |||||
| deleteAllInspectorVars, | |||||
| isInspectVarEdited, | |||||
| resetToLastRunVar, | |||||
| invalidateSysVarValues, | |||||
| resetConversationVar, | |||||
| invalidateConversationVarValues, | |||||
| configsMap, | |||||
| ]) | ]) | ||||
| return ( | return ( |
| export * from './use-workflow-start-run' | export * from './use-workflow-start-run' | ||||
| export * from './use-is-chat-mode' | export * from './use-is-chat-mode' | ||||
| export * from './use-workflow-refresh-draft' | export * from './use-workflow-refresh-draft' | ||||
| export * from './use-fetch-workflow-inspect-vars' | |||||
| export * from './use-inspect-vars-crud' | |||||
| export * from './use-configs-map' |
| import { useMemo } from 'react' | |||||
| import { useStore } from '@/app/components/workflow/store' | |||||
| export const useConfigsMap = () => { | |||||
| const appId = useStore(s => s.appId) | |||||
| return useMemo(() => { | |||||
| return { | |||||
| conversationVarsUrl: `apps/${appId}/workflows/draft/conversation-variables`, | |||||
| systemVarsUrl: `apps/${appId}/workflows/draft/system-variables`, | |||||
| } | |||||
| }, [appId]) | |||||
| } |
| import { useCallback } from 'react' | |||||
| import type { NodeWithVar, VarInInspect } from '@/types/workflow' | import type { NodeWithVar, VarInInspect } from '@/types/workflow' | ||||
| import { useWorkflowStore } from '../../workflow/store' | |||||
| import { useWorkflowStore } from '@/app/components/workflow/store' | |||||
| import { useStoreApi } from 'reactflow' | import { useStoreApi } from 'reactflow' | ||||
| import type { Node } from '@/app/components/workflow/types' | import type { Node } from '@/app/components/workflow/types' | ||||
| import { fetchAllInspectVars } from '@/service/workflow' | import { fetchAllInspectVars } from '@/service/workflow' | ||||
| import { useInvalidateConversationVarValues, useInvalidateSysVarValues } from '@/service/use-workflow' | import { useInvalidateConversationVarValues, useInvalidateSysVarValues } from '@/service/use-workflow' | ||||
| import { useNodesInteractionsWithoutSync } from '../../workflow/hooks/use-nodes-interactions-without-sync' | |||||
| const useSetWorkflowVarsWithValue = () => { | |||||
| import { useNodesInteractionsWithoutSync } from '@/app/components/workflow/hooks/use-nodes-interactions-without-sync' | |||||
| import { useConfigsMap } from './use-configs-map' | |||||
| export const useSetWorkflowVarsWithValue = () => { | |||||
| const workflowStore = useWorkflowStore() | const workflowStore = useWorkflowStore() | ||||
| const { setNodesWithInspectVars, appId } = workflowStore.getState() | |||||
| const store = useStoreApi() | const store = useStoreApi() | ||||
| const invalidateConversationVarValues = useInvalidateConversationVarValues(appId) | |||||
| const invalidateSysVarValues = useInvalidateSysVarValues(appId) | |||||
| const { conversationVarsUrl, systemVarsUrl } = useConfigsMap() | |||||
| const invalidateConversationVarValues = useInvalidateConversationVarValues(conversationVarsUrl) | |||||
| const invalidateSysVarValues = useInvalidateSysVarValues(systemVarsUrl) | |||||
| const { handleCancelAllNodeSuccessStatus } = useNodesInteractionsWithoutSync() | const { handleCancelAllNodeSuccessStatus } = useNodesInteractionsWithoutSync() | ||||
| const setInspectVarsToStore = (inspectVars: VarInInspect[]) => { | |||||
| const setInspectVarsToStore = useCallback((inspectVars: VarInInspect[]) => { | |||||
| const { setNodesWithInspectVars } = workflowStore.getState() | |||||
| const { getNodes } = store.getState() | const { getNodes } = store.getState() | ||||
| const nodeArr = getNodes() | const nodeArr = getNodes() | ||||
| const nodesKeyValue: Record<string, Node> = {} | const nodesKeyValue: Record<string, Node> = {} | ||||
| return nodeWithVar | return nodeWithVar | ||||
| }) | }) | ||||
| setNodesWithInspectVars(res) | setNodesWithInspectVars(res) | ||||
| } | |||||
| }, [workflowStore, store]) | |||||
| const fetchInspectVars = async () => { | |||||
| const fetchInspectVars = useCallback(async () => { | |||||
| const { appId } = workflowStore.getState() | |||||
| invalidateConversationVarValues() | invalidateConversationVarValues() | ||||
| invalidateSysVarValues() | invalidateSysVarValues() | ||||
| const data = await fetchAllInspectVars(appId) | const data = await fetchAllInspectVars(appId) | ||||
| setInspectVarsToStore(data) | setInspectVarsToStore(data) | ||||
| handleCancelAllNodeSuccessStatus() // to make sure clear node output show the unset status | handleCancelAllNodeSuccessStatus() // to make sure clear node output show the unset status | ||||
| } | |||||
| }, [workflowStore, invalidateConversationVarValues, invalidateSysVarValues, setInspectVarsToStore, handleCancelAllNodeSuccessStatus]) | |||||
| return { | return { | ||||
| fetchInspectVars, | fetchInspectVars, | ||||
| } | } | ||||
| } | } | ||||
| export default useSetWorkflowVarsWithValue |
| import { fetchNodeInspectVars } from '@/service/workflow' | |||||
| import { useStore, useWorkflowStore } from '@/app/components/workflow/store' | |||||
| import type { ValueSelector } from '@/app/components/workflow/types' | |||||
| import type { VarInInspect } from '@/types/workflow' | |||||
| import { VarInInspectType } from '@/types/workflow' | |||||
| import { | |||||
| useDeleteAllInspectorVars, | |||||
| useDeleteInspectVar, | |||||
| useDeleteNodeInspectorVars, | |||||
| useEditInspectorVar, | |||||
| useInvalidateConversationVarValues, | |||||
| useInvalidateSysVarValues, | |||||
| useResetConversationVar, | |||||
| useResetToLastRunValue, | |||||
| } from '@/service/use-workflow' | |||||
| import { useCallback } from 'react' | |||||
| import { isConversationVar, isENV, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils' | |||||
| import produce from 'immer' | |||||
| import type { Node } from '@/app/components/workflow/types' | |||||
| import { useNodesInteractionsWithoutSync } from '@/app/components/workflow/hooks/use-nodes-interactions-without-sync' | |||||
| import { useEdgesInteractionsWithoutSync } from '@/app/components/workflow/hooks/use-edges-interactions-without-sync' | |||||
| import { useConfigsMap } from './use-configs-map' | |||||
| export const useInspectVarsCrud = () => { | |||||
| const workflowStore = useWorkflowStore() | |||||
| const appId = useStore(s => s.appId) | |||||
| const { conversationVarsUrl, systemVarsUrl } = useConfigsMap() | |||||
| const invalidateConversationVarValues = useInvalidateConversationVarValues(conversationVarsUrl) | |||||
| const { mutateAsync: doResetConversationVar } = useResetConversationVar(appId) | |||||
| const { mutateAsync: doResetToLastRunValue } = useResetToLastRunValue(appId) | |||||
| const invalidateSysVarValues = useInvalidateSysVarValues(systemVarsUrl) | |||||
| const { mutateAsync: doDeleteAllInspectorVars } = useDeleteAllInspectorVars(appId) | |||||
| const { mutate: doDeleteNodeInspectorVars } = useDeleteNodeInspectorVars(appId) | |||||
| const { mutate: doDeleteInspectVar } = useDeleteInspectVar(appId) | |||||
| const { mutateAsync: doEditInspectorVar } = useEditInspectorVar(appId) | |||||
| const { handleCancelNodeSuccessStatus } = useNodesInteractionsWithoutSync() | |||||
| const { handleEdgeCancelRunningStatus } = useEdgesInteractionsWithoutSync() | |||||
| const getNodeInspectVars = useCallback((nodeId: string) => { | |||||
| const { nodesWithInspectVars } = workflowStore.getState() | |||||
| const node = nodesWithInspectVars.find(node => node.nodeId === nodeId) | |||||
| return node | |||||
| }, [workflowStore]) | |||||
| const getVarId = useCallback((nodeId: string, varName: string) => { | |||||
| const node = getNodeInspectVars(nodeId) | |||||
| if (!node) | |||||
| return undefined | |||||
| const varId = node.vars.find((varItem) => { | |||||
| return varItem.selector[1] === varName | |||||
| })?.id | |||||
| return varId | |||||
| }, [getNodeInspectVars]) | |||||
| const getInspectVar = useCallback((nodeId: string, name: string): VarInInspect | undefined => { | |||||
| const node = getNodeInspectVars(nodeId) | |||||
| if (!node) | |||||
| return undefined | |||||
| const variable = node.vars.find((varItem) => { | |||||
| return varItem.name === name | |||||
| }) | |||||
| return variable | |||||
| }, [getNodeInspectVars]) | |||||
| const hasSetInspectVar = useCallback((nodeId: string, name: string, sysVars: VarInInspect[], conversationVars: VarInInspect[]) => { | |||||
| const isEnv = isENV([nodeId]) | |||||
| if (isEnv) // always have value | |||||
| return true | |||||
| const isSys = isSystemVar([nodeId]) | |||||
| if (isSys) | |||||
| return sysVars.some(varItem => varItem.selector?.[1]?.replace('sys.', '') === name) | |||||
| const isChatVar = isConversationVar([nodeId]) | |||||
| if (isChatVar) | |||||
| return conversationVars.some(varItem => varItem.selector?.[1] === name) | |||||
| return getInspectVar(nodeId, name) !== undefined | |||||
| }, [getInspectVar]) | |||||
| const hasNodeInspectVars = useCallback((nodeId: string) => { | |||||
| return !!getNodeInspectVars(nodeId) | |||||
| }, [getNodeInspectVars]) | |||||
| const fetchInspectVarValue = useCallback(async (selector: ValueSelector) => { | |||||
| const { | |||||
| appId, | |||||
| setNodeInspectVars, | |||||
| } = workflowStore.getState() | |||||
| const nodeId = selector[0] | |||||
| const isSystemVar = nodeId === 'sys' | |||||
| const isConversationVar = nodeId === 'conversation' | |||||
| if (isSystemVar) { | |||||
| invalidateSysVarValues() | |||||
| return | |||||
| } | |||||
| if (isConversationVar) { | |||||
| invalidateConversationVarValues() | |||||
| return | |||||
| } | |||||
| const vars = await fetchNodeInspectVars(appId, nodeId) | |||||
| setNodeInspectVars(nodeId, vars) | |||||
| }, [workflowStore, invalidateSysVarValues, invalidateConversationVarValues]) | |||||
| // after last run would call this | |||||
| const appendNodeInspectVars = useCallback((nodeId: string, payload: VarInInspect[], allNodes: Node[]) => { | |||||
| const { | |||||
| nodesWithInspectVars, | |||||
| setNodesWithInspectVars, | |||||
| } = workflowStore.getState() | |||||
| const nodes = produce(nodesWithInspectVars, (draft) => { | |||||
| const nodeInfo = allNodes.find(node => node.id === nodeId) | |||||
| if (nodeInfo) { | |||||
| const index = draft.findIndex(node => node.nodeId === nodeId) | |||||
| if (index === -1) { | |||||
| draft.unshift({ | |||||
| nodeId, | |||||
| nodeType: nodeInfo.data.type, | |||||
| title: nodeInfo.data.title, | |||||
| vars: payload, | |||||
| nodePayload: nodeInfo.data, | |||||
| }) | |||||
| } | |||||
| else { | |||||
| draft[index].vars = payload | |||||
| // put the node to the topAdd commentMore actions | |||||
| draft.unshift(draft.splice(index, 1)[0]) | |||||
| } | |||||
| } | |||||
| }) | |||||
| setNodesWithInspectVars(nodes) | |||||
| handleCancelNodeSuccessStatus(nodeId) | |||||
| }, [workflowStore, handleCancelNodeSuccessStatus]) | |||||
| const hasNodeInspectVar = useCallback((nodeId: string, varId: string) => { | |||||
| const { nodesWithInspectVars } = workflowStore.getState() | |||||
| const targetNode = nodesWithInspectVars.find(item => item.nodeId === nodeId) | |||||
| if(!targetNode || !targetNode.vars) | |||||
| return false | |||||
| return targetNode.vars.some(item => item.id === varId) | |||||
| }, [workflowStore]) | |||||
| const deleteInspectVar = useCallback(async (nodeId: string, varId: string) => { | |||||
| const { deleteInspectVar } = workflowStore.getState() | |||||
| if(hasNodeInspectVar(nodeId, varId)) { | |||||
| await doDeleteInspectVar(varId) | |||||
| deleteInspectVar(nodeId, varId) | |||||
| } | |||||
| }, [doDeleteInspectVar, workflowStore, hasNodeInspectVar]) | |||||
| const resetConversationVar = useCallback(async (varId: string) => { | |||||
| await doResetConversationVar(varId) | |||||
| invalidateConversationVarValues() | |||||
| }, [doResetConversationVar, invalidateConversationVarValues]) | |||||
| const deleteNodeInspectorVars = useCallback(async (nodeId: string) => { | |||||
| const { deleteNodeInspectVars } = workflowStore.getState() | |||||
| if (hasNodeInspectVars(nodeId)) { | |||||
| await doDeleteNodeInspectorVars(nodeId) | |||||
| deleteNodeInspectVars(nodeId) | |||||
| } | |||||
| }, [doDeleteNodeInspectorVars, workflowStore, hasNodeInspectVars]) | |||||
| const deleteAllInspectorVars = useCallback(async () => { | |||||
| const { deleteAllInspectVars } = workflowStore.getState() | |||||
| await doDeleteAllInspectorVars() | |||||
| await invalidateConversationVarValues() | |||||
| await invalidateSysVarValues() | |||||
| deleteAllInspectVars() | |||||
| handleEdgeCancelRunningStatus() | |||||
| }, [doDeleteAllInspectorVars, invalidateConversationVarValues, invalidateSysVarValues, workflowStore, handleEdgeCancelRunningStatus]) | |||||
| const editInspectVarValue = useCallback(async (nodeId: string, varId: string, value: any) => { | |||||
| const { setInspectVarValue } = workflowStore.getState() | |||||
| await doEditInspectorVar({ | |||||
| varId, | |||||
| value, | |||||
| }) | |||||
| setInspectVarValue(nodeId, varId, value) | |||||
| if (nodeId === VarInInspectType.conversation) | |||||
| invalidateConversationVarValues() | |||||
| if (nodeId === VarInInspectType.system) | |||||
| invalidateSysVarValues() | |||||
| }, [doEditInspectorVar, invalidateConversationVarValues, invalidateSysVarValues, workflowStore]) | |||||
| const renameInspectVarName = useCallback(async (nodeId: string, oldName: string, newName: string) => { | |||||
| const { renameInspectVarName } = workflowStore.getState() | |||||
| const varId = getVarId(nodeId, oldName) | |||||
| if (!varId) | |||||
| return | |||||
| const newSelector = [nodeId, newName] | |||||
| await doEditInspectorVar({ | |||||
| varId, | |||||
| name: newName, | |||||
| }) | |||||
| renameInspectVarName(nodeId, varId, newSelector) | |||||
| }, [doEditInspectorVar, getVarId, workflowStore]) | |||||
| const isInspectVarEdited = useCallback((nodeId: string, name: string) => { | |||||
| const inspectVar = getInspectVar(nodeId, name) | |||||
| if (!inspectVar) | |||||
| return false | |||||
| return inspectVar.edited | |||||
| }, [getInspectVar]) | |||||
| const resetToLastRunVar = useCallback(async (nodeId: string, varId: string) => { | |||||
| const { resetToLastRunVar } = workflowStore.getState() | |||||
| const isSysVar = nodeId === 'sys' | |||||
| const data = await doResetToLastRunValue(varId) | |||||
| if(isSysVar) | |||||
| invalidateSysVarValues() | |||||
| else | |||||
| resetToLastRunVar(nodeId, varId, data.value) | |||||
| }, [doResetToLastRunValue, invalidateSysVarValues, workflowStore]) | |||||
| return { | |||||
| hasNodeInspectVars, | |||||
| hasSetInspectVar, | |||||
| fetchInspectVarValue, | |||||
| editInspectVarValue, | |||||
| renameInspectVarName, | |||||
| appendNodeInspectVars, | |||||
| deleteInspectVar, | |||||
| deleteNodeInspectorVars, | |||||
| deleteAllInspectorVars, | |||||
| isInspectVarEdited, | |||||
| resetToLastRunVar, | |||||
| invalidateSysVarValues, | |||||
| resetConversationVar, | |||||
| invalidateConversationVarValues, | |||||
| } | |||||
| } |
| import { noop } from 'lodash-es' | import { noop } from 'lodash-es' | ||||
| import { useNodesSyncDraft } from './use-nodes-sync-draft' | import { useNodesSyncDraft } from './use-nodes-sync-draft' | ||||
| import { useInvalidAllLastRun } from '@/service/use-workflow' | import { useInvalidAllLastRun } from '@/service/use-workflow' | ||||
| import useSetWorkflowVarsWithValue from './use-fetch-workflow-inspect-vars' | |||||
| import { useSetWorkflowVarsWithValue } from './use-fetch-workflow-inspect-vars' | |||||
| export const useWorkflowRun = () => { | export const useWorkflowRun = () => { | ||||
| const store = useStoreApi() | const store = useStoreApi() |
| } from 'zustand' | } from 'zustand' | ||||
| import { createStore } from 'zustand/vanilla' | import { createStore } from 'zustand/vanilla' | ||||
| import { HooksStoreContext } from './provider' | import { HooksStoreContext } from './provider' | ||||
| import type { IOtherOptions } from '@/service/base' | |||||
| import type { VarInInspect } from '@/types/workflow' | |||||
| import type { | |||||
| Node, | |||||
| ValueSelector, | |||||
| } from '@/app/components/workflow/types' | |||||
| type CommonHooksFnMap = { | type CommonHooksFnMap = { | ||||
| doSyncWorkflowDraft: ( | doSyncWorkflowDraft: ( | ||||
| handleBackupDraft: () => void | handleBackupDraft: () => void | ||||
| handleLoadBackupDraft: () => void | handleLoadBackupDraft: () => void | ||||
| handleRestoreFromPublishedWorkflow: (...args: any[]) => void | handleRestoreFromPublishedWorkflow: (...args: any[]) => void | ||||
| handleRun: (...args: any[]) => void | |||||
| handleRun: (params: any, callback?: IOtherOptions,) => void | |||||
| handleStopRun: (...args: any[]) => void | handleStopRun: (...args: any[]) => void | ||||
| handleStartWorkflowRun: () => void | handleStartWorkflowRun: () => void | ||||
| handleWorkflowStartRunInWorkflow: () => void | handleWorkflowStartRunInWorkflow: () => void | ||||
| handleWorkflowStartRunInChatflow: () => void | handleWorkflowStartRunInChatflow: () => void | ||||
| fetchInspectVars: () => Promise<void> | |||||
| hasNodeInspectVars: (nodeId: string) => boolean | |||||
| hasSetInspectVar: (nodeId: string, name: string, sysVars: VarInInspect[], conversationVars: VarInInspect[]) => boolean | |||||
| fetchInspectVarValue: (selector: ValueSelector) => Promise<void> | |||||
| editInspectVarValue: (nodeId: string, varId: string, value: any) => Promise<void> | |||||
| renameInspectVarName: (nodeId: string, oldName: string, newName: string) => Promise<void> | |||||
| appendNodeInspectVars: (nodeId: string, payload: VarInInspect[], allNodes: Node[]) => void | |||||
| deleteInspectVar: (nodeId: string, varId: string) => Promise<void> | |||||
| deleteNodeInspectorVars: (nodeId: string) => Promise<void> | |||||
| deleteAllInspectorVars: () => Promise<void> | |||||
| isInspectVarEdited: (nodeId: string, name: string) => boolean | |||||
| resetToLastRunVar: (nodeId: string, varId: string) => Promise<void> | |||||
| invalidateSysVarValues: () => void | |||||
| resetConversationVar: (varId: string) => Promise<void> | |||||
| invalidateConversationVarValues: () => void | |||||
| configsMap?: { | |||||
| conversationVarsUrl: string | |||||
| systemVarsUrl: string | |||||
| } | |||||
| } | } | ||||
| export type Shape = { | export type Shape = { | ||||
| handleStartWorkflowRun = noop, | handleStartWorkflowRun = noop, | ||||
| handleWorkflowStartRunInWorkflow = noop, | handleWorkflowStartRunInWorkflow = noop, | ||||
| handleWorkflowStartRunInChatflow = noop, | handleWorkflowStartRunInChatflow = noop, | ||||
| fetchInspectVars = async () => noop(), | |||||
| hasNodeInspectVars = () => false, | |||||
| hasSetInspectVar = () => false, | |||||
| fetchInspectVarValue = async () => noop(), | |||||
| editInspectVarValue = async () => noop(), | |||||
| renameInspectVarName = async () => noop(), | |||||
| appendNodeInspectVars = () => noop(), | |||||
| deleteInspectVar = async () => noop(), | |||||
| deleteNodeInspectorVars = async () => noop(), | |||||
| deleteAllInspectorVars = async () => noop(), | |||||
| isInspectVarEdited = () => false, | |||||
| resetToLastRunVar = async () => noop(), | |||||
| invalidateSysVarValues = noop, | |||||
| resetConversationVar = async () => noop(), | |||||
| invalidateConversationVarValues = noop, | |||||
| }: Partial<Shape>) => { | }: Partial<Shape>) => { | ||||
| return createStore<Shape>(set => ({ | return createStore<Shape>(set => ({ | ||||
| refreshAll: props => set(state => ({ ...state, ...props })), | refreshAll: props => set(state => ({ ...state, ...props })), | ||||
| handleStartWorkflowRun, | handleStartWorkflowRun, | ||||
| handleWorkflowStartRunInWorkflow, | handleWorkflowStartRunInWorkflow, | ||||
| handleWorkflowStartRunInChatflow, | handleWorkflowStartRunInChatflow, | ||||
| fetchInspectVars, | |||||
| hasNodeInspectVars, | |||||
| hasSetInspectVar, | |||||
| fetchInspectVarValue, | |||||
| editInspectVarValue, | |||||
| renameInspectVarName, | |||||
| appendNodeInspectVars, | |||||
| deleteInspectVar, | |||||
| deleteNodeInspectorVars, | |||||
| deleteAllInspectorVars, | |||||
| isInspectVarEdited, | |||||
| resetToLastRunVar, | |||||
| invalidateSysVarValues, | |||||
| resetConversationVar, | |||||
| invalidateConversationVarValues, | |||||
| })) | })) | ||||
| } | } | ||||
| export * from './use-workflow-mode' | export * from './use-workflow-mode' | ||||
| export * from './use-format-time-from-now' | export * from './use-format-time-from-now' | ||||
| export * from './use-workflow-refresh-draft' | export * from './use-workflow-refresh-draft' | ||||
| export * from './use-inspect-vars-crud' | |||||
| export * from './use-set-workflow-vars-with-value' |
| import { fetchNodeInspectVars } from '@/service/workflow' | |||||
| import { useStore, useWorkflowStore } from '../store' | |||||
| import type { ValueSelector } from '../types' | |||||
| import type { VarInInspect } from '@/types/workflow' | |||||
| import { VarInInspectType } from '@/types/workflow' | |||||
| import { useStore } from '../store' | |||||
| import { useHooksStore } from '@/app/components/workflow/hooks-store' | |||||
| import { | import { | ||||
| useConversationVarValues, | useConversationVarValues, | ||||
| useDeleteAllInspectorVars, | |||||
| useDeleteInspectVar, | |||||
| useDeleteNodeInspectorVars, | |||||
| useEditInspectorVar, | |||||
| useInvalidateConversationVarValues, | |||||
| useInvalidateSysVarValues, | |||||
| useResetConversationVar, | |||||
| useResetToLastRunValue, | |||||
| useSysVarValues, | useSysVarValues, | ||||
| } from '@/service/use-workflow' | } from '@/service/use-workflow' | ||||
| import { useCallback } from 'react' | |||||
| import { isConversationVar, isENV, isSystemVar } from '../nodes/_base/components/variable/utils' | |||||
| import produce from 'immer' | |||||
| import type { Node } from '@/app/components/workflow/types' | |||||
| import { useNodesInteractionsWithoutSync } from './use-nodes-interactions-without-sync' | |||||
| import { useEdgesInteractionsWithoutSync } from './use-edges-interactions-without-sync' | |||||
| const useInspectVarsCrud = () => { | const useInspectVarsCrud = () => { | ||||
| const workflowStore = useWorkflowStore() | |||||
| const nodesWithInspectVars = useStore(s => s.nodesWithInspectVars) | const nodesWithInspectVars = useStore(s => s.nodesWithInspectVars) | ||||
| const { | |||||
| appId, | |||||
| setNodeInspectVars, | |||||
| setInspectVarValue, | |||||
| renameInspectVarName: renameInspectVarNameInStore, | |||||
| deleteAllInspectVars: deleteAllInspectVarsInStore, | |||||
| deleteNodeInspectVars: deleteNodeInspectVarsInStore, | |||||
| deleteInspectVar: deleteInspectVarInStore, | |||||
| setNodesWithInspectVars, | |||||
| resetToLastRunVar: resetToLastRunVarInStore, | |||||
| } = workflowStore.getState() | |||||
| const { data: conversationVars } = useConversationVarValues(appId) | |||||
| const invalidateConversationVarValues = useInvalidateConversationVarValues(appId) | |||||
| const { mutateAsync: doResetConversationVar } = useResetConversationVar(appId) | |||||
| const { mutateAsync: doResetToLastRunValue } = useResetToLastRunValue(appId) | |||||
| const { data: systemVars } = useSysVarValues(appId) | |||||
| const invalidateSysVarValues = useInvalidateSysVarValues(appId) | |||||
| const { mutateAsync: doDeleteAllInspectorVars } = useDeleteAllInspectorVars(appId) | |||||
| const { mutate: doDeleteNodeInspectorVars } = useDeleteNodeInspectorVars(appId) | |||||
| const { mutate: doDeleteInspectVar } = useDeleteInspectVar(appId) | |||||
| const { mutateAsync: doEditInspectorVar } = useEditInspectorVar(appId) | |||||
| const { handleCancelNodeSuccessStatus } = useNodesInteractionsWithoutSync() | |||||
| const { handleEdgeCancelRunningStatus } = useEdgesInteractionsWithoutSync() | |||||
| const getNodeInspectVars = useCallback((nodeId: string) => { | |||||
| const node = nodesWithInspectVars.find(node => node.nodeId === nodeId) | |||||
| return node | |||||
| }, [nodesWithInspectVars]) | |||||
| const getVarId = useCallback((nodeId: string, varName: string) => { | |||||
| const node = getNodeInspectVars(nodeId) | |||||
| if (!node) | |||||
| return undefined | |||||
| const varId = node.vars.find((varItem) => { | |||||
| return varItem.selector[1] === varName | |||||
| })?.id | |||||
| return varId | |||||
| }, [getNodeInspectVars]) | |||||
| const getInspectVar = useCallback((nodeId: string, name: string): VarInInspect | undefined => { | |||||
| const node = getNodeInspectVars(nodeId) | |||||
| if (!node) | |||||
| return undefined | |||||
| const variable = node.vars.find((varItem) => { | |||||
| return varItem.name === name | |||||
| }) | |||||
| return variable | |||||
| }, [getNodeInspectVars]) | |||||
| const hasSetInspectVar = useCallback((nodeId: string, name: string, sysVars: VarInInspect[], conversationVars: VarInInspect[]) => { | |||||
| const isEnv = isENV([nodeId]) | |||||
| if (isEnv) // always have value | |||||
| return true | |||||
| const isSys = isSystemVar([nodeId]) | |||||
| if (isSys) | |||||
| return sysVars.some(varItem => varItem.selector?.[1]?.replace('sys.', '') === name) | |||||
| const isChatVar = isConversationVar([nodeId]) | |||||
| if (isChatVar) | |||||
| return conversationVars.some(varItem => varItem.selector?.[1] === name) | |||||
| return getInspectVar(nodeId, name) !== undefined | |||||
| }, [getInspectVar]) | |||||
| const hasNodeInspectVars = useCallback((nodeId: string) => { | |||||
| return !!getNodeInspectVars(nodeId) | |||||
| }, [getNodeInspectVars]) | |||||
| const fetchInspectVarValue = async (selector: ValueSelector) => { | |||||
| const nodeId = selector[0] | |||||
| const isSystemVar = nodeId === 'sys' | |||||
| const isConversationVar = nodeId === 'conversation' | |||||
| if (isSystemVar) { | |||||
| invalidateSysVarValues() | |||||
| return | |||||
| } | |||||
| if (isConversationVar) { | |||||
| invalidateConversationVarValues() | |||||
| return | |||||
| } | |||||
| const vars = await fetchNodeInspectVars(appId, nodeId) | |||||
| setNodeInspectVars(nodeId, vars) | |||||
| } | |||||
| // after last run would call this | |||||
| const appendNodeInspectVars = (nodeId: string, payload: VarInInspect[], allNodes: Node[]) => { | |||||
| const nodes = produce(nodesWithInspectVars, (draft) => { | |||||
| const nodeInfo = allNodes.find(node => node.id === nodeId) | |||||
| if (nodeInfo) { | |||||
| const index = draft.findIndex(node => node.nodeId === nodeId) | |||||
| if (index === -1) { | |||||
| draft.unshift({ | |||||
| nodeId, | |||||
| nodeType: nodeInfo.data.type, | |||||
| title: nodeInfo.data.title, | |||||
| vars: payload, | |||||
| nodePayload: nodeInfo.data, | |||||
| }) | |||||
| } | |||||
| else { | |||||
| draft[index].vars = payload | |||||
| // put the node to the top | |||||
| draft.unshift(draft.splice(index, 1)[0]) | |||||
| } | |||||
| } | |||||
| }) | |||||
| setNodesWithInspectVars(nodes) | |||||
| handleCancelNodeSuccessStatus(nodeId) | |||||
| } | |||||
| const hasNodeInspectVar = (nodeId: string, varId: string) => { | |||||
| const targetNode = nodesWithInspectVars.find(item => item.nodeId === nodeId) | |||||
| if(!targetNode || !targetNode.vars) | |||||
| return false | |||||
| return targetNode.vars.some(item => item.id === varId) | |||||
| } | |||||
| const deleteInspectVar = async (nodeId: string, varId: string) => { | |||||
| if(hasNodeInspectVar(nodeId, varId)) { | |||||
| await doDeleteInspectVar(varId) | |||||
| deleteInspectVarInStore(nodeId, varId) | |||||
| } | |||||
| } | |||||
| const resetConversationVar = async (varId: string) => { | |||||
| await doResetConversationVar(varId) | |||||
| invalidateConversationVarValues() | |||||
| } | |||||
| const deleteNodeInspectorVars = async (nodeId: string) => { | |||||
| if (hasNodeInspectVars(nodeId)) { | |||||
| await doDeleteNodeInspectorVars(nodeId) | |||||
| deleteNodeInspectVarsInStore(nodeId) | |||||
| } | |||||
| } | |||||
| const deleteAllInspectorVars = async () => { | |||||
| await doDeleteAllInspectorVars() | |||||
| await invalidateConversationVarValues() | |||||
| await invalidateSysVarValues() | |||||
| deleteAllInspectVarsInStore() | |||||
| handleEdgeCancelRunningStatus() | |||||
| } | |||||
| const editInspectVarValue = useCallback(async (nodeId: string, varId: string, value: any) => { | |||||
| await doEditInspectorVar({ | |||||
| varId, | |||||
| value, | |||||
| }) | |||||
| setInspectVarValue(nodeId, varId, value) | |||||
| if (nodeId === VarInInspectType.conversation) | |||||
| invalidateConversationVarValues() | |||||
| if (nodeId === VarInInspectType.system) | |||||
| invalidateSysVarValues() | |||||
| }, [doEditInspectorVar, invalidateConversationVarValues, invalidateSysVarValues, setInspectVarValue]) | |||||
| const renameInspectVarName = async (nodeId: string, oldName: string, newName: string) => { | |||||
| const varId = getVarId(nodeId, oldName) | |||||
| if (!varId) | |||||
| return | |||||
| const newSelector = [nodeId, newName] | |||||
| await doEditInspectorVar({ | |||||
| varId, | |||||
| name: newName, | |||||
| }) | |||||
| renameInspectVarNameInStore(nodeId, varId, newSelector) | |||||
| } | |||||
| const isInspectVarEdited = useCallback((nodeId: string, name: string) => { | |||||
| const inspectVar = getInspectVar(nodeId, name) | |||||
| if (!inspectVar) | |||||
| return false | |||||
| return inspectVar.edited | |||||
| }, [getInspectVar]) | |||||
| const resetToLastRunVar = async (nodeId: string, varId: string) => { | |||||
| const isSysVar = nodeId === 'sys' | |||||
| const data = await doResetToLastRunValue(varId) | |||||
| if(isSysVar) | |||||
| invalidateSysVarValues() | |||||
| else | |||||
| resetToLastRunVarInStore(nodeId, varId, data.value) | |||||
| } | |||||
| const configsMap = useHooksStore(s => s.configsMap) | |||||
| const { data: conversationVars } = useConversationVarValues(configsMap?.conversationVarsUrl) | |||||
| const { data: systemVars } = useSysVarValues(configsMap?.systemVarsUrl) | |||||
| const hasNodeInspectVars = useHooksStore(s => s.hasNodeInspectVars) | |||||
| const hasSetInspectVar = useHooksStore(s => s.hasSetInspectVar) | |||||
| const fetchInspectVarValue = useHooksStore(s => s.fetchInspectVarValue) | |||||
| const editInspectVarValue = useHooksStore(s => s.editInspectVarValue) | |||||
| const renameInspectVarName = useHooksStore(s => s.renameInspectVarName) | |||||
| const appendNodeInspectVars = useHooksStore(s => s.appendNodeInspectVars) | |||||
| const deleteInspectVar = useHooksStore(s => s.deleteInspectVar) | |||||
| const deleteNodeInspectorVars = useHooksStore(s => s.deleteNodeInspectorVars) | |||||
| const deleteAllInspectorVars = useHooksStore(s => s.deleteAllInspectorVars) | |||||
| const isInspectVarEdited = useHooksStore(s => s.isInspectVarEdited) | |||||
| const resetToLastRunVar = useHooksStore(s => s.resetToLastRunVar) | |||||
| const invalidateSysVarValues = useHooksStore(s => s.invalidateSysVarValues) | |||||
| const resetConversationVar = useHooksStore(s => s.resetConversationVar) | |||||
| const invalidateConversationVarValues = useHooksStore(s => s.invalidateConversationVarValues) | |||||
| return { | return { | ||||
| conversationVars: conversationVars || [], | conversationVars: conversationVars || [], |
| import { useHooksStore } from '@/app/components/workflow/hooks-store' | |||||
| export const useSetWorkflowVarsWithValue = () => { | |||||
| const fetchInspectVars = useHooksStore(s => s.fetchInspectVars) | |||||
| return { | |||||
| fetchInspectVars, | |||||
| } | |||||
| } |
| useNodesSyncDraft, | useNodesSyncDraft, | ||||
| usePanelInteractions, | usePanelInteractions, | ||||
| useSelectionInteractions, | useSelectionInteractions, | ||||
| useSetWorkflowVarsWithValue, | |||||
| useShortcuts, | useShortcuts, | ||||
| useWorkflow, | useWorkflow, | ||||
| useWorkflowReadOnly, | useWorkflowReadOnly, | ||||
| import DatasetsDetailProvider from './datasets-detail-store/provider' | import DatasetsDetailProvider from './datasets-detail-store/provider' | ||||
| import { HooksStoreContextProvider } from './hooks-store' | import { HooksStoreContextProvider } from './hooks-store' | ||||
| import type { Shape as HooksStoreShape } from './hooks-store' | import type { Shape as HooksStoreShape } from './hooks-store' | ||||
| import useSetWorkflowVarsWithValue from '../workflow-app/hooks/use-fetch-workflow-inspect-vars' | |||||
| const nodeTypes = { | const nodeTypes = { | ||||
| [CUSTOM_NODE]: CustomNode, | [CUSTOM_NODE]: CustomNode, |
| import { useTranslation } from 'react-i18next' | import { useTranslation } from 'react-i18next' | ||||
| import { produce, setAutoFreeze } from 'immer' | import { produce, setAutoFreeze } from 'immer' | ||||
| import { uniqBy } from 'lodash-es' | import { uniqBy } from 'lodash-es' | ||||
| import { useWorkflowRun } from '../../hooks' | |||||
| import { | |||||
| useSetWorkflowVarsWithValue, | |||||
| useWorkflowRun, | |||||
| } from '../../hooks' | |||||
| import { NodeRunningStatus, WorkflowRunningStatus } from '../../types' | import { NodeRunningStatus, WorkflowRunningStatus } from '../../types' | ||||
| import { useWorkflowStore } from '../../store' | import { useWorkflowStore } from '../../store' | ||||
| import { DEFAULT_ITER_TIMES, DEFAULT_LOOP_TIMES } from '../../constants' | import { DEFAULT_ITER_TIMES, DEFAULT_LOOP_TIMES } from '../../constants' | ||||
| import { getThreadMessages } from '@/app/components/base/chat/utils' | import { getThreadMessages } from '@/app/components/base/chat/utils' | ||||
| import { useInvalidAllLastRun } from '@/service/use-workflow' | import { useInvalidAllLastRun } from '@/service/use-workflow' | ||||
| import { useParams } from 'next/navigation' | import { useParams } from 'next/navigation' | ||||
| import useSetWorkflowVarsWithValue from '@/app/components/workflow-app/hooks/use-fetch-workflow-inspect-vars' | |||||
| type GetAbortController = (abortController: AbortController) => void | type GetAbortController = (abortController: AbortController) => void | ||||
| type SendCallback = { | type SendCallback = { | ||||
| }, | }, | ||||
| }, | }, | ||||
| ) | ) | ||||
| }, [threadMessages, chatTree.length, updateCurrentQAOnTree, handleResponding, formSettings?.inputsForm, handleRun, notify, t, config?.suggested_questions_after_answer?.enabled]) | |||||
| }, [threadMessages, chatTree.length, updateCurrentQAOnTree, handleResponding, formSettings?.inputsForm, handleRun, notify, t, config?.suggested_questions_after_answer?.enabled, fetchInspectVars, invalidAllLastRun]) | |||||
| return { | return { | ||||
| conversationId: conversationId.current, | conversationId: conversationId.current, |
| const useConversationVarValuesKey = [NAME_SPACE, 'conversation-variable'] | const useConversationVarValuesKey = [NAME_SPACE, 'conversation-variable'] | ||||
| export const useConversationVarValues = (appId: string) => { | |||||
| export const useConversationVarValues = (url?: string) => { | |||||
| return useQuery({ | return useQuery({ | ||||
| queryKey: [...useConversationVarValuesKey, appId], | |||||
| enabled: !!url, | |||||
| queryKey: [...useConversationVarValuesKey, url], | |||||
| queryFn: async () => { | queryFn: async () => { | ||||
| const { items } = (await get(`apps/${appId}/workflows/draft/conversation-variables`)) as { items: VarInInspect[] } | |||||
| const { items } = (await get(url || '')) as { items: VarInInspect[] } | |||||
| return items | return items | ||||
| }, | }, | ||||
| }) | }) | ||||
| } | } | ||||
| export const useInvalidateConversationVarValues = (appId: string) => { | |||||
| return useInvalid([...useConversationVarValuesKey, appId]) | |||||
| export const useInvalidateConversationVarValues = (url: string) => { | |||||
| return useInvalid([...useConversationVarValuesKey, url]) | |||||
| } | } | ||||
| export const useResetConversationVar = (appId: string) => { | export const useResetConversationVar = (appId: string) => { | ||||
| } | } | ||||
| export const useSysVarValuesKey = [NAME_SPACE, 'sys-variable'] | export const useSysVarValuesKey = [NAME_SPACE, 'sys-variable'] | ||||
| export const useSysVarValues = (appId: string) => { | |||||
| export const useSysVarValues = (url?: string) => { | |||||
| return useQuery({ | return useQuery({ | ||||
| queryKey: [...useSysVarValuesKey, appId], | |||||
| enabled: !!url, | |||||
| queryKey: [...useSysVarValuesKey, url], | |||||
| queryFn: async () => { | queryFn: async () => { | ||||
| const { items } = (await get(`apps/${appId}/workflows/draft/system-variables`)) as { items: VarInInspect[] } | |||||
| const { items } = (await get(url || '')) as { items: VarInInspect[] } | |||||
| return items | return items | ||||
| }, | }, | ||||
| }) | }) | ||||
| } | } | ||||
| export const useInvalidateSysVarValues = (appId: string) => { | |||||
| return useInvalid([...useSysVarValuesKey, appId]) | |||||
| export const useInvalidateSysVarValues = (url: string) => { | |||||
| return useInvalid([...useSysVarValuesKey, url]) | |||||
| } | } | ||||
| export const useDeleteAllInspectorVars = (appId: string) => { | export const useDeleteAllInspectorVars = (appId: string) => { |