Co-authored-by: Joel <iamjoel007@gmail.com>tags/1.6.0
| @@ -7,7 +7,10 @@ import { WorkflowWithInnerContext } from '@/app/components/workflow' | |||
| import type { WorkflowProps } from '@/app/components/workflow' | |||
| import WorkflowChildren from './workflow-children' | |||
| import { | |||
| useConfigsMap, | |||
| useInspectVarsCrud, | |||
| useNodesSyncDraft, | |||
| useSetWorkflowVarsWithValue, | |||
| useWorkflowRefreshDraft, | |||
| useWorkflowRun, | |||
| useWorkflowStartRun, | |||
| @@ -61,6 +64,24 @@ const WorkflowMain = ({ | |||
| handleWorkflowStartRunInChatflow, | |||
| handleWorkflowStartRunInWorkflow, | |||
| } = 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(() => { | |||
| return { | |||
| @@ -75,6 +96,22 @@ const WorkflowMain = ({ | |||
| handleStartWorkflowRun, | |||
| handleWorkflowStartRunInChatflow, | |||
| handleWorkflowStartRunInWorkflow, | |||
| fetchInspectVars, | |||
| hasNodeInspectVars, | |||
| hasSetInspectVar, | |||
| fetchInspectVarValue, | |||
| editInspectVarValue, | |||
| renameInspectVarName, | |||
| appendNodeInspectVars, | |||
| deleteInspectVar, | |||
| deleteNodeInspectorVars, | |||
| deleteAllInspectorVars, | |||
| isInspectVarEdited, | |||
| resetToLastRunVar, | |||
| invalidateSysVarValues, | |||
| resetConversationVar, | |||
| invalidateConversationVarValues, | |||
| configsMap, | |||
| } | |||
| }, [ | |||
| syncWorkflowDraftWhenPageClose, | |||
| @@ -88,6 +125,22 @@ const WorkflowMain = ({ | |||
| handleStartWorkflowRun, | |||
| handleWorkflowStartRunInChatflow, | |||
| handleWorkflowStartRunInWorkflow, | |||
| fetchInspectVars, | |||
| hasNodeInspectVars, | |||
| hasSetInspectVar, | |||
| fetchInspectVarValue, | |||
| editInspectVarValue, | |||
| renameInspectVarName, | |||
| appendNodeInspectVars, | |||
| deleteInspectVar, | |||
| deleteNodeInspectorVars, | |||
| deleteAllInspectorVars, | |||
| isInspectVarEdited, | |||
| resetToLastRunVar, | |||
| invalidateSysVarValues, | |||
| resetConversationVar, | |||
| invalidateConversationVarValues, | |||
| configsMap, | |||
| ]) | |||
| return ( | |||
| @@ -5,3 +5,6 @@ export * from './use-workflow-run' | |||
| export * from './use-workflow-start-run' | |||
| export * from './use-is-chat-mode' | |||
| export * from './use-workflow-refresh-draft' | |||
| export * from './use-fetch-workflow-inspect-vars' | |||
| export * from './use-inspect-vars-crud' | |||
| export * from './use-configs-map' | |||
| @@ -0,0 +1,12 @@ | |||
| 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]) | |||
| } | |||
| @@ -1,19 +1,23 @@ | |||
| import { useCallback } from 'react' | |||
| import type { NodeWithVar, VarInInspect } from '@/types/workflow' | |||
| import { useWorkflowStore } from '../../workflow/store' | |||
| import { useWorkflowStore } from '@/app/components/workflow/store' | |||
| import { useStoreApi } from 'reactflow' | |||
| import type { Node } from '@/app/components/workflow/types' | |||
| import { fetchAllInspectVars } from '@/service/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 { setNodesWithInspectVars, appId } = workflowStore.getState() | |||
| 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 setInspectVarsToStore = (inspectVars: VarInInspect[]) => { | |||
| const setInspectVarsToStore = useCallback((inspectVars: VarInInspect[]) => { | |||
| const { setNodesWithInspectVars } = workflowStore.getState() | |||
| const { getNodes } = store.getState() | |||
| const nodeArr = getNodes() | |||
| const nodesKeyValue: Record<string, Node> = {} | |||
| @@ -51,18 +55,17 @@ const useSetWorkflowVarsWithValue = () => { | |||
| return nodeWithVar | |||
| }) | |||
| setNodesWithInspectVars(res) | |||
| } | |||
| }, [workflowStore, store]) | |||
| const fetchInspectVars = async () => { | |||
| const fetchInspectVars = useCallback(async () => { | |||
| const { appId } = workflowStore.getState() | |||
| invalidateConversationVarValues() | |||
| invalidateSysVarValues() | |||
| const data = await fetchAllInspectVars(appId) | |||
| setInspectVarsToStore(data) | |||
| handleCancelAllNodeSuccessStatus() // to make sure clear node output show the unset status | |||
| } | |||
| }, [workflowStore, invalidateConversationVarValues, invalidateSysVarValues, setInspectVarsToStore, handleCancelAllNodeSuccessStatus]) | |||
| return { | |||
| fetchInspectVars, | |||
| } | |||
| } | |||
| export default useSetWorkflowVarsWithValue | |||
| @@ -0,0 +1,234 @@ | |||
| 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, | |||
| } | |||
| } | |||
| @@ -20,7 +20,7 @@ import type { VersionHistory } from '@/types/workflow' | |||
| import { noop } from 'lodash-es' | |||
| import { useNodesSyncDraft } from './use-nodes-sync-draft' | |||
| 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 = () => { | |||
| const store = useStoreApi() | |||
| @@ -7,6 +7,12 @@ import { | |||
| } from 'zustand' | |||
| import { createStore } from 'zustand/vanilla' | |||
| 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 = { | |||
| doSyncWorkflowDraft: ( | |||
| @@ -22,11 +28,30 @@ type CommonHooksFnMap = { | |||
| handleBackupDraft: () => void | |||
| handleLoadBackupDraft: () => void | |||
| handleRestoreFromPublishedWorkflow: (...args: any[]) => void | |||
| handleRun: (...args: any[]) => void | |||
| handleRun: (params: any, callback?: IOtherOptions,) => void | |||
| handleStopRun: (...args: any[]) => void | |||
| handleStartWorkflowRun: () => void | |||
| handleWorkflowStartRunInWorkflow: () => 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 = { | |||
| @@ -45,6 +70,21 @@ export const createHooksStore = ({ | |||
| handleStartWorkflowRun = noop, | |||
| handleWorkflowStartRunInWorkflow = 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>) => { | |||
| return createStore<Shape>(set => ({ | |||
| refreshAll: props => set(state => ({ ...state, ...props })), | |||
| @@ -59,6 +99,21 @@ export const createHooksStore = ({ | |||
| handleStartWorkflowRun, | |||
| handleWorkflowStartRunInWorkflow, | |||
| handleWorkflowStartRunInChatflow, | |||
| fetchInspectVars, | |||
| hasNodeInspectVars, | |||
| hasSetInspectVar, | |||
| fetchInspectVarValue, | |||
| editInspectVarValue, | |||
| renameInspectVarName, | |||
| appendNodeInspectVars, | |||
| deleteInspectVar, | |||
| deleteNodeInspectorVars, | |||
| deleteAllInspectorVars, | |||
| isInspectVarEdited, | |||
| resetToLastRunVar, | |||
| invalidateSysVarValues, | |||
| resetConversationVar, | |||
| invalidateConversationVarValues, | |||
| })) | |||
| } | |||
| @@ -17,3 +17,5 @@ export * from './use-workflow-interactions' | |||
| export * from './use-workflow-mode' | |||
| export * from './use-format-time-from-now' | |||
| export * from './use-workflow-refresh-draft' | |||
| export * from './use-inspect-vars-crud' | |||
| export * from './use-set-workflow-vars-with-value' | |||
| @@ -1,217 +1,29 @@ | |||
| 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 { | |||
| useConversationVarValues, | |||
| useDeleteAllInspectorVars, | |||
| useDeleteInspectVar, | |||
| useDeleteNodeInspectorVars, | |||
| useEditInspectorVar, | |||
| useInvalidateConversationVarValues, | |||
| useInvalidateSysVarValues, | |||
| useResetConversationVar, | |||
| useResetToLastRunValue, | |||
| useSysVarValues, | |||
| } 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 workflowStore = useWorkflowStore() | |||
| 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 { | |||
| conversationVars: conversationVars || [], | |||
| @@ -0,0 +1,9 @@ | |||
| import { useHooksStore } from '@/app/components/workflow/hooks-store' | |||
| export const useSetWorkflowVarsWithValue = () => { | |||
| const fetchInspectVars = useHooksStore(s => s.fetchInspectVars) | |||
| return { | |||
| fetchInspectVars, | |||
| } | |||
| } | |||
| @@ -42,6 +42,7 @@ import { | |||
| useNodesSyncDraft, | |||
| usePanelInteractions, | |||
| useSelectionInteractions, | |||
| useSetWorkflowVarsWithValue, | |||
| useShortcuts, | |||
| useWorkflow, | |||
| useWorkflowReadOnly, | |||
| @@ -82,7 +83,6 @@ import Confirm from '@/app/components/base/confirm' | |||
| import DatasetsDetailProvider from './datasets-detail-store/provider' | |||
| import { HooksStoreContextProvider } from './hooks-store' | |||
| import type { Shape as HooksStoreShape } from './hooks-store' | |||
| import useSetWorkflowVarsWithValue from '../workflow-app/hooks/use-fetch-workflow-inspect-vars' | |||
| const nodeTypes = { | |||
| [CUSTOM_NODE]: CustomNode, | |||
| @@ -8,7 +8,10 @@ import { | |||
| import { useTranslation } from 'react-i18next' | |||
| import { produce, setAutoFreeze } from 'immer' | |||
| import { uniqBy } from 'lodash-es' | |||
| import { useWorkflowRun } from '../../hooks' | |||
| import { | |||
| useSetWorkflowVarsWithValue, | |||
| useWorkflowRun, | |||
| } from '../../hooks' | |||
| import { NodeRunningStatus, WorkflowRunningStatus } from '../../types' | |||
| import { useWorkflowStore } from '../../store' | |||
| import { DEFAULT_ITER_TIMES, DEFAULT_LOOP_TIMES } from '../../constants' | |||
| @@ -32,7 +35,6 @@ import type { FileEntity } from '@/app/components/base/file-uploader/types' | |||
| import { getThreadMessages } from '@/app/components/base/chat/utils' | |||
| import { useInvalidAllLastRun } from '@/service/use-workflow' | |||
| import { useParams } from 'next/navigation' | |||
| import useSetWorkflowVarsWithValue from '@/app/components/workflow-app/hooks/use-fetch-workflow-inspect-vars' | |||
| type GetAbortController = (abortController: AbortController) => void | |||
| type SendCallback = { | |||
| @@ -499,7 +501,7 @@ export const useChat = ( | |||
| }, | |||
| }, | |||
| ) | |||
| }, [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 { | |||
| conversationId: conversationId.current, | |||
| @@ -113,18 +113,19 @@ export const useInvalidAllLastRun = (appId: string) => { | |||
| const useConversationVarValuesKey = [NAME_SPACE, 'conversation-variable'] | |||
| export const useConversationVarValues = (appId: string) => { | |||
| export const useConversationVarValues = (url?: string) => { | |||
| return useQuery({ | |||
| queryKey: [...useConversationVarValuesKey, appId], | |||
| enabled: !!url, | |||
| queryKey: [...useConversationVarValuesKey, url], | |||
| 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 | |||
| }, | |||
| }) | |||
| } | |||
| export const useInvalidateConversationVarValues = (appId: string) => { | |||
| return useInvalid([...useConversationVarValuesKey, appId]) | |||
| export const useInvalidateConversationVarValues = (url: string) => { | |||
| return useInvalid([...useConversationVarValuesKey, url]) | |||
| } | |||
| export const useResetConversationVar = (appId: string) => { | |||
| @@ -146,18 +147,19 @@ export const useResetToLastRunValue = (appId: string) => { | |||
| } | |||
| export const useSysVarValuesKey = [NAME_SPACE, 'sys-variable'] | |||
| export const useSysVarValues = (appId: string) => { | |||
| export const useSysVarValues = (url?: string) => { | |||
| return useQuery({ | |||
| queryKey: [...useSysVarValuesKey, appId], | |||
| enabled: !!url, | |||
| queryKey: [...useSysVarValuesKey, url], | |||
| 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 | |||
| }, | |||
| }) | |||
| } | |||
| export const useInvalidateSysVarValues = (appId: string) => { | |||
| return useInvalid([...useSysVarValuesKey, appId]) | |||
| export const useInvalidateSysVarValues = (url: string) => { | |||
| return useInvalid([...useSysVarValuesKey, url]) | |||
| } | |||
| export const useDeleteAllInspectorVars = (appId: string) => { | |||