mirror of
https://github.com/langgenius/dify.git
synced 2026-05-03 08:58:09 +08:00
feat: Trigger single run in sub-graph after modal opens
This commit is contained in:
@ -4,11 +4,13 @@ import type { SyncWorkflowDraft, SyncWorkflowDraftCallback } from '../types'
|
||||
import type { Shape as HooksStoreShape } from '@/app/components/workflow/hooks-store'
|
||||
import type { NestedNodeConfig } from '@/app/components/workflow/nodes/_base/types'
|
||||
import type { Edge, Node } from '@/app/components/workflow/types'
|
||||
import { useCallback, useMemo } from 'react'
|
||||
import { useCallback, useEffect, useMemo } from 'react'
|
||||
import { useStoreApi } from 'reactflow'
|
||||
import { InteractionMode, WorkflowWithInnerContext } from '@/app/components/workflow'
|
||||
import { useNodesInteractions } from '@/app/components/workflow/hooks'
|
||||
import { useSetWorkflowVarsWithValue } from '@/app/components/workflow/hooks/use-fetch-workflow-inspect-vars'
|
||||
import { useInspectVarsCrudCommon } from '@/app/components/workflow/hooks/use-inspect-vars-crud-common'
|
||||
import { useWorkflowStore } from '@/app/components/workflow/store'
|
||||
import { BlockEnum } from '@/app/components/workflow/types'
|
||||
import { FlowType } from '@/types/common'
|
||||
import { useAvailableNodesMetaData } from '../hooks'
|
||||
@ -24,6 +26,9 @@ type SubGraphMainBaseProps = {
|
||||
selectableNodeTypes?: BlockEnum[]
|
||||
onSave?: (nodes: Node[], edges: Edge[]) => void
|
||||
onSyncWorkflowDraft?: SyncWorkflowDraft
|
||||
isOpen: boolean
|
||||
pendingSingleRun?: boolean
|
||||
onPendingSingleRunHandled?: () => void
|
||||
}
|
||||
|
||||
type SubGraphMainProps
|
||||
@ -50,8 +55,13 @@ const SubGraphMain: FC<SubGraphMainProps> = (props) => {
|
||||
selectableNodeTypes,
|
||||
onSave,
|
||||
onSyncWorkflowDraft,
|
||||
isOpen,
|
||||
pendingSingleRun,
|
||||
onPendingSingleRunHandled,
|
||||
} = props
|
||||
const reactFlowStore = useStoreApi()
|
||||
const workflowStore = useWorkflowStore()
|
||||
const { handleNodeSelect } = useNodesInteractions()
|
||||
const availableNodesMetaData = useAvailableNodesMetaData()
|
||||
const flowType = configsMap?.flowType ?? FlowType.appFlow
|
||||
const flowId = configsMap?.flowId ?? ''
|
||||
@ -91,6 +101,32 @@ const SubGraphMain: FC<SubGraphMainProps> = (props) => {
|
||||
}
|
||||
}, [handleSyncSubGraphDraft, onSyncWorkflowDraft])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen || !pendingSingleRun)
|
||||
return
|
||||
|
||||
const { getNodes } = reactFlowStore.getState()
|
||||
const currentNodes = getNodes()
|
||||
const hasExtractorNode = currentNodes.some(node => node.id === extractorNodeId)
|
||||
if (!hasExtractorNode)
|
||||
return
|
||||
|
||||
// NodePanel listens for pendingSingleRun only when the extractor node is selected in this subgraph.
|
||||
handleNodeSelect(extractorNodeId, false, true)
|
||||
|
||||
// Defer run until the selection is applied and the panel is ready.
|
||||
const frame = requestAnimationFrame(() => {
|
||||
const store = workflowStore.getState()
|
||||
store.setPendingSingleRun({
|
||||
nodeId: extractorNodeId,
|
||||
action: 'run',
|
||||
})
|
||||
onPendingSingleRunHandled?.()
|
||||
})
|
||||
|
||||
return () => cancelAnimationFrame(frame)
|
||||
}, [extractorNodeId, handleNodeSelect, isOpen, onPendingSingleRunHandled, pendingSingleRun, reactFlowStore, workflowStore])
|
||||
|
||||
const resolvedSelectableTypes = useMemo(() => {
|
||||
if (selectableNodeTypes && selectableNodeTypes.length > 0)
|
||||
return selectableNodeTypes
|
||||
|
||||
@ -32,6 +32,7 @@ const defaultViewport: Viewport = {
|
||||
|
||||
const SubGraphContent: FC<SubGraphProps> = (props) => {
|
||||
const {
|
||||
isOpen,
|
||||
toolNodeId,
|
||||
paramKey,
|
||||
toolParamValue,
|
||||
@ -41,6 +42,8 @@ const SubGraphContent: FC<SubGraphProps> = (props) => {
|
||||
selectableNodeTypes,
|
||||
onSave,
|
||||
onSyncWorkflowDraft,
|
||||
pendingSingleRun,
|
||||
onPendingSingleRunHandled,
|
||||
} = props
|
||||
|
||||
const isAgentVariant = props.variant === 'agent'
|
||||
@ -230,6 +233,9 @@ const SubGraphContent: FC<SubGraphProps> = (props) => {
|
||||
title={sourceTitle}
|
||||
extractorNodeId={`${toolNodeId}_ext_${paramKey}`}
|
||||
configsMap={configsMap}
|
||||
isOpen={isOpen}
|
||||
pendingSingleRun={pendingSingleRun}
|
||||
onPendingSingleRunHandled={onPendingSingleRunHandled}
|
||||
nestedNodeConfig={props.nestedNodeConfig}
|
||||
onNestedNodeConfigChange={props.onNestedNodeConfigChange}
|
||||
selectableNodeTypes={selectableNodeTypes}
|
||||
@ -253,6 +259,9 @@ const SubGraphContent: FC<SubGraphProps> = (props) => {
|
||||
title={sourceTitle}
|
||||
extractorNodeId={`${toolNodeId}_ext_${paramKey}`}
|
||||
configsMap={configsMap}
|
||||
isOpen={isOpen}
|
||||
pendingSingleRun={pendingSingleRun}
|
||||
onPendingSingleRunHandled={onPendingSingleRunHandled}
|
||||
nestedNodeConfig={props.nestedNodeConfig}
|
||||
onNestedNodeConfigChange={props.onNestedNodeConfigChange}
|
||||
selectableNodeTypes={selectableNodeTypes}
|
||||
|
||||
@ -19,6 +19,7 @@ export type SyncWorkflowDraft = (
|
||||
export type SubGraphVariant = 'agent' | 'assemble'
|
||||
|
||||
type BaseSubGraphProps = {
|
||||
isOpen: boolean
|
||||
toolNodeId: string
|
||||
paramKey: string
|
||||
configsMap?: HooksStoreShape['configsMap']
|
||||
@ -28,6 +29,8 @@ type BaseSubGraphProps = {
|
||||
selectableNodeTypes?: BlockEnum[]
|
||||
onSave?: (nodes: Node[], edges: Edge[]) => void
|
||||
onSyncWorkflowDraft?: SyncWorkflowDraft
|
||||
pendingSingleRun?: boolean
|
||||
onPendingSingleRunHandled?: () => void
|
||||
}
|
||||
|
||||
export type AgentSubGraphProps = BaseSubGraphProps & {
|
||||
|
||||
@ -13,7 +13,6 @@ import type {
|
||||
import {
|
||||
memo,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
@ -26,7 +25,7 @@ import { useHooksStore } from '@/app/components/workflow/hooks-store'
|
||||
import { NULL_STRATEGY } from '@/app/components/workflow/nodes/_base/constants'
|
||||
import { VarKindType as VarKindTypeEnum } from '@/app/components/workflow/nodes/_base/types'
|
||||
import { Type } from '@/app/components/workflow/nodes/llm/types'
|
||||
import { useStore, useWorkflowStore } from '@/app/components/workflow/store'
|
||||
import { useStore } from '@/app/components/workflow/store'
|
||||
import { BlockEnum } from '@/app/components/workflow/types'
|
||||
import { useGetLanguage } from '@/context/i18n'
|
||||
import { useStrategyProviders } from '@/service/use-strategy'
|
||||
@ -99,7 +98,6 @@ const MixedVariableTextInput = ({
|
||||
const [isContextGenerateModalOpen, setIsContextGenerateModalOpen] = useState(false)
|
||||
const contextGenerateModalRef = useRef<ContextGenerateModalHandle>(null)
|
||||
const [pendingRunAfterSubGraphOpen, setPendingRunAfterSubGraphOpen] = useState(false)
|
||||
const workflowStore = useWorkflowStore()
|
||||
|
||||
const nodesByIdMap = useMemo(() => {
|
||||
return availableNodes.reduce((acc, node) => {
|
||||
@ -359,35 +357,19 @@ const MixedVariableTextInput = ({
|
||||
setPendingRunAfterSubGraphOpen(false)
|
||||
}, [])
|
||||
|
||||
const handlePendingSingleRunHandled = useCallback(() => {
|
||||
setPendingRunAfterSubGraphOpen(false)
|
||||
}, [])
|
||||
|
||||
const handleCloseContextGenerateModal = useCallback(() => {
|
||||
setIsContextGenerateModalOpen(false)
|
||||
}, [])
|
||||
|
||||
const handleOpenInternalViewAndRun = useCallback(() => {
|
||||
setIsSubGraphModalOpen(true)
|
||||
if (!isSubGraphModalOpen)
|
||||
setIsSubGraphModalOpen(true)
|
||||
setPendingRunAfterSubGraphOpen(true)
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
if (!isSubGraphModalOpen || !pendingRunAfterSubGraphOpen)
|
||||
return
|
||||
|
||||
const extractorNodeId = assembleExtractorNodeId || (toolNodeId && paramKey ? `${toolNodeId}_ext_${paramKey}` : '')
|
||||
if (!extractorNodeId)
|
||||
return
|
||||
|
||||
const timer = setTimeout(() => {
|
||||
const store = workflowStore()
|
||||
store.setInitShowLastRunTab(true)
|
||||
store.setPendingSingleRun({
|
||||
nodeId: extractorNodeId,
|
||||
action: 'run',
|
||||
})
|
||||
setPendingRunAfterSubGraphOpen(false)
|
||||
}, 300)
|
||||
|
||||
return () => clearTimeout(timer)
|
||||
}, [isSubGraphModalOpen, pendingRunAfterSubGraphOpen, assembleExtractorNodeId, toolNodeId, paramKey, workflowStore])
|
||||
}, [isSubGraphModalOpen])
|
||||
|
||||
const sourceVariable: ValueSelector | undefined = detectedAgentFromValue
|
||||
? [detectedAgentFromValue.nodeId, 'context']
|
||||
@ -465,6 +447,8 @@ const MixedVariableTextInput = ({
|
||||
<SubGraphModal
|
||||
isOpen={isSubGraphModalOpen}
|
||||
onClose={handleCloseSubGraphModal}
|
||||
pendingSingleRun={pendingRunAfterSubGraphOpen}
|
||||
onPendingSingleRunHandled={handlePendingSingleRunHandled}
|
||||
variant="assemble"
|
||||
toolNodeId={toolNodeId}
|
||||
paramKey={paramKey}
|
||||
|
||||
Reference in New Issue
Block a user