Compare commits

...

2 Commits

Author SHA1 Message Date
zxhlyh
bf20f3aa8b chore: workflow performance 2025-10-11 14:02:25 +08:00
zxhlyh
c90e564d99 chore: workflow performance 2025-10-10 18:23:46 +08:00
20 changed files with 156 additions and 132 deletions

View File

@@ -3,7 +3,7 @@ import {
useCallback,
useMemo,
} from 'react'
import { useEdges, useNodes, useStore as useReactflowStore } from 'reactflow'
import { useStore as useReactflowStore } from 'reactflow'
import { RiApps2AddLine } from '@remixicon/react'
import { useTranslation } from 'react-i18next'
import {
@@ -11,7 +11,6 @@ import {
useWorkflowStore,
} from '@/app/components/workflow/store'
import {
useChecklist,
useChecklistBeforePublish,
useNodesReadOnly,
useNodesSyncDraft,
@@ -19,10 +18,6 @@ import {
import Button from '@/app/components/base/button'
import AppPublisher from '@/app/components/app/app-publisher'
import { useFeatures } from '@/app/components/base/features/hooks'
import type {
CommonEdgeType,
CommonNodeType,
} from '@/app/components/workflow/types'
import {
BlockEnum,
InputVarType,
@@ -97,18 +92,9 @@ const FeaturesTrigger = () => {
}
}, [appID, setAppDetail])
const { mutateAsync: publishWorkflow } = usePublishWorkflow()
const nodes = useNodes<CommonNodeType>()
const edges = useEdges<CommonEdgeType>()
const needWarningNodes = useChecklist(nodes, edges)
const updatePublishedWorkflow = useInvalidateAppWorkflow()
const onPublish = useCallback(async (params?: PublishWorkflowParams) => {
// First check if there are any items in the checklist
if (needWarningNodes.length > 0) {
notify({ type: 'error', message: t('workflow.panel.checklistTip') })
throw new Error('Checklist has unresolved items')
}
// Then perform the detailed validation
if (await handleCheckBeforePublish()) {
const res = await publishWorkflow({
@@ -128,7 +114,7 @@ const FeaturesTrigger = () => {
else {
throw new Error('Checklist failed')
}
}, [needWarningNodes, handleCheckBeforePublish, publishWorkflow, notify, appID, t, updatePublishedWorkflow, updateAppDetail, workflowStore, resetWorkflowVersionHistory])
}, [handleCheckBeforePublish, publishWorkflow, notify, appID, t, updatePublishedWorkflow, updateAppDetail, workflowStore, resetWorkflowVersionHistory])
const onPublisherToggle = useCallback((state: boolean) => {
if (state)

View File

@@ -2,27 +2,25 @@ import {
memo,
useCallback,
} from 'react'
import { useNodes } from 'reactflow'
import { useStore } from './store'
import {
useIsChatMode,
useNodesReadOnly,
useNodesSyncDraft,
} from './hooks'
import { type CommonNodeType, type InputVar, InputVarType, type Node } from './types'
import { type InputVar, InputVarType, type Node } from './types'
import useConfig from './nodes/start/use-config'
import type { StartNodeType } from './nodes/start/types'
import type { PromptVariable } from '@/models/debug'
import NewFeaturePanel from '@/app/components/base/features/new-feature-panel'
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
const Features = () => {
const setShowFeaturesPanel = useStore(s => s.setShowFeaturesPanel)
const isChatMode = useIsChatMode()
const { nodesReadOnly } = useNodesReadOnly()
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
const nodes = useNodes<CommonNodeType>()
const startNode = nodes.find(node => node.data.type === 'start')
const startNode = useFindNode(['sys'])
const { id, data } = startNode as Node<StartNodeType>
const { handleAddVariable } = useConfig(id, data)

View File

@@ -1,12 +1,11 @@
import {
useCallback,
} from 'react'
import { useNodes } from 'reactflow'
import { useStore as useReactFlowStore } from 'reactflow'
import {
useStore,
useWorkflowStore,
} from '../store'
import type { StartNodeType } from '../nodes/start/types'
import {
useNodesInteractions,
useNodesReadOnly,
@@ -39,8 +38,7 @@ const HeaderInNormal = ({
const setShowDebugAndPreviewPanel = useStore(s => s.setShowDebugAndPreviewPanel)
const setShowVariableInspectPanel = useStore(s => s.setShowVariableInspectPanel)
const setShowChatVariablePanel = useStore(s => s.setShowChatVariablePanel)
const nodes = useNodes<StartNodeType>()
const selectedNode = nodes.find(node => node.data.selected)
const selectedNode = useReactFlowStore(s => s.getNodes().find(node => node.data.selected))
const { handleBackupDraft } = useWorkflowRun()
const { closeAllInputFieldPanels } = useInputFieldPanel()

View File

@@ -0,0 +1,36 @@
import { useMemo } from 'react'
import { useStore } from 'reactflow'
import { useShallow } from 'zustand/react/shallow'
import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
import { BlockEnum } from '@/app/components/workflow/types'
import type { Node, ValueSelector } from '@/app/components/workflow/types'
export const useFindNode = (valueSelector: ValueSelector = [], nodes: Node[] = []) => {
const nodeFromOuterNodes = nodes.find(node => node.id === valueSelector[0])
const node = useStore(useShallow((s) => {
if (isSystemVar(valueSelector)) {
for (const n of s.nodeInternals.values()) {
if (n?.data?.type === BlockEnum.Start) {
return {
id: n.id,
data: n.data,
}
}
}
}
else {
if (!!valueSelector.length) {
const id = s.nodeInternals.get(valueSelector[0])?.id
const data = s.nodeInternals.get(valueSelector[0])?.data
if (id && data) {
return {
id,
data,
}
}
}
}
}))
return useMemo(() => nodeFromOuterNodes || node, [nodeFromOuterNodes, node])
}

View File

@@ -4,18 +4,16 @@ import {
useRef,
} from 'react'
import { useClickAway } from 'ahooks'
import { useNodes } from 'reactflow'
import PanelOperatorPopup from './nodes/_base/components/panel-operator/panel-operator-popup'
import type { Node } from './types'
import { useStore } from './store'
import { usePanelInteractions } from './hooks'
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
const NodeContextmenu = () => {
const ref = useRef(null)
const nodes = useNodes()
const { handleNodeContextmenuCancel, handlePaneContextmenuCancel } = usePanelInteractions()
const nodeMenu = useStore(s => s.nodeMenu)
const currentNode = nodes.find(node => node.id === nodeMenu?.nodeId) as Node
const currentNode = useFindNode(nodeMenu?.nodeId ? [nodeMenu.nodeId] : [])
useEffect(() => {
if (nodeMenu)

View File

@@ -1,18 +1,18 @@
import { useCallback, useMemo } from 'react'
import { useNodes, useReactFlow, useStoreApi } from 'reactflow'
import { useReactFlow, useStoreApi } from 'reactflow'
import { useTranslation } from 'react-i18next'
import type {
CommonNodeType,
Node,
ValueSelector,
VarType,
} from '@/app/components/workflow/types'
import { BlockEnum } from '@/app/components/workflow/types'
import { getNodeInfoById, isConversationVar, isENV, isRagVariableVar, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
import { isConversationVar, isENV, isRagVariableVar, isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
import { isExceptionVariable } from '@/app/components/workflow/utils'
import {
VariableLabelInSelect,
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
type VariableTagProps = {
valueSelector: ValueSelector
@@ -26,16 +26,16 @@ const VariableTag = ({
isShort,
availableNodes,
}: VariableTagProps) => {
const nodes = useNodes<CommonNodeType>()
const isRagVar = isRagVariableVar(valueSelector)
const nodeFromAvailableNodes = useFindNode(isRagVar ? [valueSelector[1]] : [valueSelector[0]], availableNodes)
const node = useMemo(() => {
if (isSystemVar(valueSelector)) {
const startNode = availableNodes?.find(n => n.data.type === BlockEnum.Start)
if (startNode)
return startNode
}
return getNodeInfoById(availableNodes || nodes, isRagVar ? valueSelector[1] : valueSelector[0])
}, [nodes, valueSelector, availableNodes, isRagVar])
return nodeFromAvailableNodes
}, [valueSelector, availableNodes, isRagVar, nodeFromAvailableNodes]) as Node
const isEnv = isENV(valueSelector)
const isChatVar = isConversationVar(valueSelector)

View File

@@ -0,0 +1,35 @@
import { memo } from 'react'
import { useTranslation } from 'react-i18next'
import type { AssignerNodeOperation } from '../types'
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
import {
VariableLabelInNode,
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
import Badge from '@/app/components/base/badge'
type OperationItemProps = {
value: AssignerNodeOperation
}
const i18nPrefix = 'workflow.nodes.assigner'
const OperationItem = ({ value }: OperationItemProps) => {
const { t } = useTranslation()
const variable = value.variable_selector
const node = useFindNode(variable)
if (!variable || variable.length === 0)
return null
return (
<VariableLabelInNode
variables={variable}
nodeType={node?.data.type}
nodeTitle={node?.data.title}
rightSlot={
value.operation && <Badge className='!ml-auto shrink-0' text={t(`${i18nPrefix}.operations.${value.operation}`)} />
}
/>
)
}
export default memo(OperationItem)

View File

@@ -1,6 +1,6 @@
import { useCallback } from 'react'
import {
useNodes,
useStoreApi,
} from 'reactflow'
import { uniqBy } from 'lodash-es'
import {
@@ -15,12 +15,14 @@ import type {
import { AssignerNodeInputType, WriteMode } from './types'
export const useGetAvailableVars = () => {
const nodes: Node[] = useNodes()
const store = useStoreApi()
const { getBeforeNodesInSameBranchIncludeParent } = useWorkflow()
const { getNodeAvailableVars } = useWorkflowVariables()
const isChatMode = useIsChatMode()
const getAvailableVars = useCallback((nodeId: string, handleId: string, filterVar: (v: Var) => boolean, hideEnv = false) => {
const availableNodes: Node[] = []
const { getNodes } = store.getState()
const nodes = getNodes()
const currentNode = nodes.find(node => node.id === nodeId)!
if (!currentNode)
@@ -52,7 +54,7 @@ export const useGetAvailableVars = () => {
isChatMode,
filterVar,
})
}, [nodes, getBeforeNodesInSameBranchIncludeParent, getNodeAvailableVars, isChatMode])
}, [store, getBeforeNodesInSameBranchIncludeParent, getNodeAvailableVars, isChatMode])
return getAvailableVars
}

View File

@@ -1,14 +1,14 @@
import type { FC } from 'react'
import React from 'react'
import { useNodes } from 'reactflow'
import { useTranslation } from 'react-i18next'
import type { AssignerNodeType } from './types'
import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
import { BlockEnum, type Node, type NodeProps } from '@/app/components/workflow/types'
import type { NodeProps } from '@/app/components/workflow/types'
import {
VariableLabelInNode,
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
import Badge from '@/app/components/base/badge'
import OperationItem from './components/operation-item'
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
const i18nPrefix = 'workflow.nodes.assigner'
@@ -16,7 +16,7 @@ const NodeComponent: FC<NodeProps<AssignerNodeType>> = ({
data,
}) => {
const { t } = useTranslation()
const nodes: Node[] = useNodes()
const node = useFindNode((data as any).assigned_variable_selector)
if (data.version === '2') {
const { items: operationItems } = data
const validOperationItems = operationItems?.filter(item =>
@@ -37,22 +37,7 @@ const NodeComponent: FC<NodeProps<AssignerNodeType>> = ({
return (
<div className='relative flex flex-col items-start gap-0.5 self-stretch px-3 py-1'>
{operationItems.map((value, index) => {
const variable = value.variable_selector
if (!variable || variable.length === 0)
return null
const isSystem = isSystemVar(variable)
const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0])
return (
<VariableLabelInNode
key={index}
variables={variable}
nodeType={node?.data.type}
nodeTitle={node?.data.title}
rightSlot={
value.operation && <Badge className='!ml-auto shrink-0' text={t(`${i18nPrefix}.operations.${value.operation}`)} />
}
/>
)
return <OperationItem key={index} value={value} />
})}
</div>
)
@@ -62,8 +47,6 @@ const NodeComponent: FC<NodeProps<AssignerNodeType>> = ({
if (!variable || variable.length === 0)
return null
const isSystem = isSystemVar(variable)
const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0])
return (
<div className='relative flex flex-col items-start gap-0.5 self-stretch px-3 py-1'>

View File

@@ -1,13 +1,12 @@
import type { FC } from 'react'
import React from 'react'
import { useNodes } from 'reactflow'
import { useTranslation } from 'react-i18next'
import type { DocExtractorNodeType } from './types'
import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
import { BlockEnum, type Node, type NodeProps } from '@/app/components/workflow/types'
import type { NodeProps } from '@/app/components/workflow/types'
import {
VariableLabelInNode,
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
const i18nPrefix = 'workflow.nodes.docExtractor'
@@ -15,15 +14,12 @@ const NodeComponent: FC<NodeProps<DocExtractorNodeType>> = ({
data,
}) => {
const { t } = useTranslation()
const nodes: Node[] = useNodes()
const { variable_selector: variable } = data
const node = useFindNode(variable)
if (!variable || variable.length === 0)
return null
const isSystem = isSystemVar(variable)
const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0])
return (
<div className='relative px-3'>
<div className='system-2xs-medium-uppercase mb-1 text-text-tertiary'>{t(`${i18nPrefix}.inputVar`)}</div>

View File

@@ -3,7 +3,6 @@ import {
useMemo,
} from 'react'
import { useTranslation } from 'react-i18next'
import { useNodes } from 'reactflow'
import { ComparisonOperator } from '../types'
import {
comparisonOperatorNotRequireValue,
@@ -12,13 +11,10 @@ import {
import { FILE_TYPE_OPTIONS, TRANSFER_METHOD } from '../../constants'
import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
import { isExceptionVariable } from '@/app/components/workflow/utils'
import type {
CommonNodeType,
Node,
} from '@/app/components/workflow/types'
import {
VariableLabelInText,
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
type ConditionValueProps = {
variableSelector: string[]
@@ -33,11 +29,10 @@ const ConditionValue = ({
value,
}: ConditionValueProps) => {
const { t } = useTranslation()
const nodes = useNodes()
const node = useFindNode(variableSelector)
const variableName = labelName || (isSystemVar(variableSelector) ? variableSelector.slice(0).join('.') : variableSelector.slice(1).join('.'))
const operatorName = isComparisonOperatorNeedTranslate(operator) ? t(`workflow.nodes.ifElse.comparisonOperator.${operator}`) : operator
const notHasValue = comparisonOperatorNotRequireValue(operator)
const node: Node<CommonNodeType> | undefined = nodes.find(n => n.id === variableSelector[0]) as Node<CommonNodeType>
const isException = isExceptionVariable(variableName, node?.data.type)
const formatValue = useMemo(() => {
if (notHasValue)

View File

@@ -1,13 +1,12 @@
import type { FC } from 'react'
import React from 'react'
import { useNodes } from 'reactflow'
import { useTranslation } from 'react-i18next'
import type { ListFilterNodeType } from './types'
import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
import { BlockEnum, type Node, type NodeProps } from '@/app/components/workflow/types'
import type { NodeProps } from '@/app/components/workflow/types'
import {
VariableLabelInNode,
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
const i18nPrefix = 'workflow.nodes.listFilter'
@@ -15,15 +14,12 @@ const NodeComponent: FC<NodeProps<ListFilterNodeType>> = ({
data,
}) => {
const { t } = useTranslation()
const nodes: Node[] = useNodes()
const { variable } = data
const node = useFindNode(variable)
if (!variable || variable.length === 0)
return null
const isSystem = isSystemVar(variable)
const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0])
return (
<div className='relative px-3'>
<div className='system-2xs-medium-uppercase mb-1 text-text-tertiary'>{t(`${i18nPrefix}.inputVar`)}</div>

View File

@@ -3,11 +3,8 @@ import {
useMemo,
} from 'react'
import { useTranslation } from 'react-i18next'
import { useNodes } from 'reactflow'
import { useStore } from '../../../store'
import { BlockEnum } from '../../../types'
import type {
Node,
ValueSelector,
VarType,
} from '../../../types'
@@ -18,12 +15,8 @@ import {
} from '../hooks'
import { filterVar } from '../utils'
import AddVariable from './add-variable'
import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
import cn from '@/utils/classnames'
import { isExceptionVariable } from '@/app/components/workflow/utils'
import {
VariableLabelInNode,
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
import VariableLabelItem from './variable-label-item'
const i18nPrefix = 'workflow.nodes.variableAssigner'
type GroupItem = {
@@ -44,7 +37,6 @@ const NodeGroupItem = ({
const { t } = useTranslation()
const enteringNodePayload = useStore(s => s.enteringNodePayload)
const hoveringAssignVariableGroupId = useStore(s => s.hoveringAssignVariableGroupId)
const nodes: Node[] = useNodes()
const {
handleGroupItemMouseEnter,
handleGroupItemMouseLeave,
@@ -128,21 +120,7 @@ const NodeGroupItem = ({
<div className='space-y-0.5'>
{
item.variables.map((variable = [], index) => {
const isSystem = isSystemVar(variable)
const node = isSystem ? nodes.find(node => node.data.type === BlockEnum.Start) : nodes.find(node => node.id === variable[0])
const varName = isSystem ? `sys.${variable[variable.length - 1]}` : variable.slice(1).join('.')
const isException = isExceptionVariable(varName, node?.data.type)
return (
<VariableLabelInNode
key={index}
variables={variable}
nodeType={node?.data.type}
nodeTitle={node?.data.title}
isExceptionVariable={isException}
/>
)
return <VariableLabelItem key={index} variable={variable} />
})
}
</div>

View File

@@ -0,0 +1,29 @@
import { memo } from 'react'
import type { ValueSelector } from '@/app/components/workflow/types'
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
import { isSystemVar } from '@/app/components/workflow/nodes/_base/components/variable/utils'
import { isExceptionVariable } from '@/app/components/workflow/utils'
import {
VariableLabelInNode,
} from '@/app/components/workflow/nodes/_base/components/variable/variable-label'
type VariableLabelItemProps = {
variable: ValueSelector
}
const VariableLabelItem = ({ variable }: VariableLabelItemProps) => {
const isSystem = isSystemVar(variable)
const node = useFindNode(variable)
const varName = isSystem ? `sys.${variable[variable.length - 1]}` : variable.slice(1).join('.')
const isException = isExceptionVariable(varName, node?.data.type)
return (
<VariableLabelInNode
variables={variable}
nodeType={node?.data.type}
nodeTitle={node?.data.title}
isExceptionVariable={isException}
/>
)
}
export default memo(VariableLabelItem)

View File

@@ -1,6 +1,5 @@
import { useCallback } from 'react'
import {
useNodes,
useStoreApi,
} from 'reactflow'
import { uniqBy } from 'lodash-es'
@@ -122,12 +121,14 @@ export const useVariableAssigner = () => {
}
export const useGetAvailableVars = () => {
const nodes: Node[] = useNodes()
const store = useStoreApi()
const { getBeforeNodesInSameBranchIncludeParent } = useWorkflow()
const { getNodeAvailableVars } = useWorkflowVariables()
const isChatMode = useIsChatMode()
const getAvailableVars = useCallback((nodeId: string, handleId: string, filterVar: (v: Var) => boolean, hideEnv = false) => {
const availableNodes: Node[] = []
const { getNodes } = store.getState()
const nodes = getNodes()
const currentNode = nodes.find(node => node.id === nodeId)!
if (!currentNode)
@@ -158,7 +159,7 @@ export const useGetAvailableVars = () => {
isChatMode,
filterVar,
})
}, [nodes, getBeforeNodesInSameBranchIncludeParent, getNodeAvailableVars, isChatMode])
}, [store, getBeforeNodesInSameBranchIncludeParent, getNodeAvailableVars, isChatMode])
return getAvailableVars
}

View File

@@ -1,6 +1,5 @@
import { memo, useCallback, useEffect, useImperativeHandle, useMemo } from 'react'
import { useNodes } from 'reactflow'
import { BlockEnum } from '../../types'
import type { Node } from '../../types'
import {
useStore,
useWorkflowStore,
@@ -23,6 +22,7 @@ import { getLastAnswer, isValidGeneratedAnswer } from '@/app/components/base/cha
import type { FileEntity } from '@/app/components/base/file-uploader/types'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import { EVENT_WORKFLOW_STOP } from '@/app/components/workflow/variable-inspect/types'
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
type ChatWrapperProps = {
showConversationVariableModal: boolean
@@ -42,8 +42,7 @@ const ChatWrapper = (
ref: React.RefObject<ChatWrapperRefType>;
},
) => {
const nodes = useNodes<StartNodeType>()
const startNode = nodes.find(node => node.data.type === BlockEnum.Start)
const startNode = useFindNode(['sys']) as Node<StartNodeType>
const startVariables = startNode?.data.variables
const appDetail = useAppStore(s => s.appDetail)
const workflowStore = useWorkflowStore()

View File

@@ -8,13 +8,13 @@ import {
import { RiCloseLine, RiEqualizer2Line } from '@remixicon/react'
import { useTranslation } from 'react-i18next'
import { useNodes } from 'reactflow'
import { useStore as useReactFlowStore } from 'reactflow'
import {
useWorkflowInteractions,
} from '../../hooks'
import { useEdgesInteractionsWithoutSync } from '@/app/components/workflow/hooks/use-edges-interactions-without-sync'
import { useNodesInteractionsWithoutSync } from '@/app/components/workflow/hooks/use-nodes-interactions-without-sync'
import { BlockEnum } from '../../types'
import type { Node } from '../../types'
import type { StartNodeType } from '../../nodes/start/types'
import { useResizePanel } from '../../nodes/_base/hooks/use-resize-panel'
import ChatWrapper from './chat-wrapper'
@@ -24,6 +24,7 @@ import Tooltip from '@/app/components/base/tooltip'
import ActionButton, { ActionButtonState } from '@/app/components/base/action-button'
import { useStore } from '@/app/components/workflow/store'
import { debounce, noop } from 'lodash-es'
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
export type ChatWrapperRefType = {
handleRestart: () => void
@@ -35,9 +36,8 @@ const DebugAndPreview = () => {
const { handleNodeCancelRunningStatus } = useNodesInteractionsWithoutSync()
const { handleEdgeCancelRunningStatus } = useEdgesInteractionsWithoutSync()
const [expanded, setExpanded] = useState(true)
const nodes = useNodes<StartNodeType>()
const selectedNode = nodes.find(node => node.data.selected)
const startNode = nodes.find(node => node.data.type === BlockEnum.Start)
const startNode = useFindNode(['sys']) as Node<StartNodeType>
const selectedNode = useReactFlowStore(s => s.getNodes().find(node => node.data.selected))
const variables = startNode?.data.variables || []
const visibleVariables = variables.filter(v => v.hide !== true)

View File

@@ -1,21 +1,20 @@
import {
memo,
} from 'react'
import { useNodes } from 'reactflow'
import FormItem from '../../nodes/_base/components/before-run-form/form-item'
import { BlockEnum } from '../../types'
import type { Node } from '../../types'
import {
useStore,
useWorkflowStore,
} from '../../store'
import type { StartNodeType } from '../../nodes/start/types'
import cn from '@/utils/classnames'
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
const UserInput = () => {
const workflowStore = useWorkflowStore()
const inputs = useStore(s => s.inputs)
const nodes = useNodes<StartNodeType>()
const startNode = nodes.find(node => node.data.type === BlockEnum.Start)
const startNode = useFindNode(['sys']) as Node<StartNodeType>
const variables = startNode?.data.variables || []
const visibleVariables = variables.filter(v => v.hide !== true)

View File

@@ -4,10 +4,8 @@ import {
useMemo,
} from 'react'
import { useTranslation } from 'react-i18next'
import { useNodes } from 'reactflow'
import FormItem from '../nodes/_base/components/before-run-form/form-item'
import {
BlockEnum,
InputVarType,
WorkflowRunningStatus,
} from '../types'
@@ -16,7 +14,6 @@ import {
useWorkflowStore,
} from '../store'
import { useWorkflowRun } from '../hooks'
import type { StartNodeType } from '../nodes/start/types'
import { TransferMethod } from '../../base/text-generation/types'
import Button from '@/app/components/base/button'
import {
@@ -24,6 +21,7 @@ import {
} from '@/app/components/base/chat/chat/utils'
import { useCheckInputsForms } from '@/app/components/base/chat/chat/check-input-forms-hooks'
import { useHooksStore } from '../hooks-store'
import { useFindNode } from '@/app/components/workflow/hooks/use-find-node'
type Props = {
onRun: () => void
@@ -37,19 +35,18 @@ const InputsPanel = ({ onRun }: Props) => {
setInputs: s.setInputs,
}))
const fileSettings = useHooksStore(s => s.configsMap?.fileSettings)
const nodes = useNodes<StartNodeType>()
const startNode = useFindNode(['sys'])
const files = useStore(s => s.files)
const workflowRunningData = useStore(s => s.workflowRunningData)
const {
handleRun,
} = useWorkflowRun()
const startNode = nodes.find(node => node.data.type === BlockEnum.Start)
const startVariables = startNode?.data.variables
const { checkInputsForm } = useCheckInputsForms()
const initialInputs = { ...inputs }
if (startVariables) {
startVariables.forEach((variable) => {
startVariables.forEach((variable: any) => {
if (variable.default)
initialInputs[variable.variable] = variable.default
if (inputs[variable.variable] !== undefined)
@@ -110,7 +107,7 @@ const InputsPanel = ({ onRun }: Props) => {
<>
<div className='px-4 pb-2 pt-3'>
{
variables.map((variable, index) => (
variables.map((variable: any, index: number) => (
<div
key={variable.variable}
className='mb-2 last-of-type:mb-0'

View File

@@ -1,6 +1,6 @@
import type { FC } from 'react'
import { useMemo } from 'react'
import { useNodes } from 'reactflow'
import { useStore as useReactFlowStore } from 'reactflow'
import { useTranslation } from 'react-i18next'
import { RiLoader2Line, RiStopCircleFill } from '@remixicon/react'
import Tooltip from '@/app/components/base/tooltip'
@@ -8,7 +8,6 @@ import { useStore } from '../store'
import useCurrentVars from '../hooks/use-inspect-vars-crud'
import { WorkflowRunningStatus } from '@/app/components/workflow/types'
import { NodeRunningStatus } from '@/app/components/workflow/types'
import type { CommonNodeType } from '@/app/components/workflow/types'
import { useEventEmitterContextContext } from '@/context/event-emitter'
import { EVENT_WORKFLOW_STOP } from '@/app/components/workflow/variable-inspect/types'
import cn from '@/utils/classnames'
@@ -38,8 +37,7 @@ const VariableInspectTrigger: FC = () => {
getNodesReadOnly,
} = useNodesReadOnly()
const workflowRunningData = useStore(s => s.workflowRunningData)
const nodes = useNodes<CommonNodeType>()
const isStepRunning = useMemo(() => nodes.some(node => node.data._singleRunningStatus === NodeRunningStatus.Running), [nodes])
const isStepRunning = useReactFlowStore(s => s.getNodes().some(node => node.data._singleRunningStatus === NodeRunningStatus.Running))
const isPreviewRunning = useMemo(() => {
if (!workflowRunningData)
return false