mirror of
https://git.mirrors.martin98.com/https://github.com/langgenius/dify.git
synced 2025-08-18 02:35:56 +08:00
fix: parallel branch limit
This commit is contained in:
parent
ae22015fe7
commit
f43596f226
@ -326,6 +326,7 @@ export const ITERATION_PADDING = {
|
||||
bottom: 20,
|
||||
left: 16,
|
||||
}
|
||||
export const PARALLEL_LIMIT = 10
|
||||
|
||||
export const RETRIEVAL_OUTPUT_STRUCT = `{
|
||||
"content": "",
|
||||
|
@ -17,6 +17,7 @@ import {
|
||||
useReactFlow,
|
||||
useStoreApi,
|
||||
} from 'reactflow'
|
||||
import { uniq } from 'lodash-es'
|
||||
import type { ToolDefaultValue } from '../block-selector/types'
|
||||
import type {
|
||||
Edge,
|
||||
@ -212,7 +213,7 @@ export const useNodesInteractions = () => {
|
||||
setEdges(newEdges)
|
||||
const incomesNodes = getIncomers(node, nodes, edges)
|
||||
if (incomesNodes.length) {
|
||||
const incomesNodesOutgoersId = incomesNodes.map(incomeNode => getOutgoers(incomeNode, nodes, edges)).flat().map(outgoer => outgoer.id)
|
||||
const incomesNodesOutgoersId = uniq(incomesNodes.map(incomeNode => getOutgoers(incomeNode, nodes, edges)).flat().map(outgoer => outgoer.id))
|
||||
|
||||
if (incomesNodesOutgoersId.length > 1) {
|
||||
const newNodes = produce(nodes, (draft) => {
|
||||
|
@ -6,6 +6,7 @@ import {
|
||||
} from 'react'
|
||||
import dayjs from 'dayjs'
|
||||
import { uniqBy } from 'lodash-es'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useContext } from 'use-context-selector'
|
||||
import {
|
||||
getIncomers,
|
||||
@ -29,6 +30,7 @@ import {
|
||||
useWorkflowStore,
|
||||
} from '../store'
|
||||
import {
|
||||
PARALLEL_LIMIT,
|
||||
SUPPORT_OUTPUT_VARS_NODE,
|
||||
} from '../constants'
|
||||
import { CUSTOM_NOTE_NODE } from '../note-node/constants'
|
||||
@ -59,6 +61,7 @@ export const useIsChatMode = () => {
|
||||
}
|
||||
|
||||
export const useWorkflow = () => {
|
||||
const { t } = useTranslation()
|
||||
const { locale } = useContext(I18n)
|
||||
const store = useStoreApi()
|
||||
const workflowStore = useWorkflowStore()
|
||||
@ -288,6 +291,14 @@ export const useWorkflow = () => {
|
||||
if (sourceNode.type === CUSTOM_NOTE_NODE || targetNode.type === CUSTOM_NOTE_NODE)
|
||||
return false
|
||||
|
||||
const sourceNodeOutgoers = getOutgoers(sourceNode, nodes, edges)
|
||||
|
||||
if (sourceNodeOutgoers.length > PARALLEL_LIMIT - 1) {
|
||||
const { setShowTips } = workflowStore.getState()
|
||||
setShowTips(t('workflow.common.parallelTip.limit', { num: PARALLEL_LIMIT }))
|
||||
return false
|
||||
}
|
||||
|
||||
if (sourceNode && targetNode) {
|
||||
const sourceNodeAvailableNextNodes = nodesExtraData[sourceNode.data.type].availableNextNodes
|
||||
const targetNodeAvailablePrevNodes = [...nodesExtraData[targetNode.data.type].availablePrevNodes, BlockEnum.Start]
|
||||
|
@ -69,6 +69,7 @@ import NodeContextmenu from './node-contextmenu'
|
||||
import SyncingDataModal from './syncing-data-modal'
|
||||
import UpdateDSLModal from './update-dsl-modal'
|
||||
import DSLExportConfirmModal from './dsl-export-confirm-modal'
|
||||
import LimitTips from './limit-tips'
|
||||
import {
|
||||
useStore,
|
||||
useWorkflowStore,
|
||||
@ -320,6 +321,7 @@ const Workflow: FC<WorkflowProps> = memo(({
|
||||
/>
|
||||
)
|
||||
}
|
||||
<LimitTips />
|
||||
<ReactFlow
|
||||
nodeTypes={nodeTypes}
|
||||
edgeTypes={edgeTypes}
|
||||
|
32
web/app/components/workflow/limit-tips.tsx
Normal file
32
web/app/components/workflow/limit-tips.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import {
|
||||
RiAlertFill,
|
||||
RiCloseLine,
|
||||
} from '@remixicon/react'
|
||||
import { useStore } from './store'
|
||||
import ActionButton from '@/app/components/base/action-button'
|
||||
|
||||
const LimitTips = () => {
|
||||
const showTips = useStore(s => s.showTips)
|
||||
const setShowTips = useStore(s => s.setShowTips)
|
||||
|
||||
if (!showTips)
|
||||
return null
|
||||
|
||||
return (
|
||||
<div className='absolute bottom-16 left-1/2 -translate-x-1/2 flex items-center rounded-xl p-2 h-10 border border-components-panel-border bg-components-panel-bg-blur shadow-md z-[9]'>
|
||||
<div className='flex items-center justify-center w-5 h-5'>
|
||||
<RiAlertFill className='w-4 h-4 text-text-warning-secondary' />
|
||||
</div>
|
||||
<div className='mx-1 px-1 system-xs-medium text-text-primary'>
|
||||
{showTips}
|
||||
</div>
|
||||
<ActionButton
|
||||
onClick={() => setShowTips('')}
|
||||
>
|
||||
<RiCloseLine className='w-4 h-4' />
|
||||
</ActionButton>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default LimitTips
|
@ -16,10 +16,15 @@ import BlockSelector from '../../../block-selector'
|
||||
import type { ToolDefaultValue } from '../../../block-selector/types'
|
||||
import {
|
||||
useAvailableBlocks,
|
||||
useIsChatMode,
|
||||
useNodesInteractions,
|
||||
useNodesReadOnly,
|
||||
} from '../../../hooks'
|
||||
import { useStore } from '../../../store'
|
||||
import {
|
||||
useStore,
|
||||
useWorkflowStore,
|
||||
} from '../../../store'
|
||||
import { PARALLEL_LIMIT } from '../../../constants'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
|
||||
type NodeHandleProps = {
|
||||
@ -114,11 +119,13 @@ export const NodeSourceHandle = memo(({
|
||||
}: NodeHandleProps) => {
|
||||
const { t } = useTranslation()
|
||||
const notInitialWorkflow = useStore(s => s.notInitialWorkflow)
|
||||
const workflowStore = useWorkflowStore()
|
||||
const [open, setOpen] = useState(false)
|
||||
const { handleNodeAdd } = useNodesInteractions()
|
||||
const { getNodesReadOnly } = useNodesReadOnly()
|
||||
const { availableNextBlocks } = useAvailableBlocks(data.type, data.isInIteration)
|
||||
const isConnectable = !!availableNextBlocks.length
|
||||
const isChatMode = useIsChatMode()
|
||||
|
||||
const connected = data._connectedSourceHandleIds?.includes(handleId)
|
||||
const handleOpenChange = useCallback((v: boolean) => {
|
||||
@ -126,8 +133,13 @@ export const NodeSourceHandle = memo(({
|
||||
}, [])
|
||||
const handleHandleClick = useCallback((e: MouseEvent) => {
|
||||
e.stopPropagation()
|
||||
if (data._connectedSourceHandleIds!.length > PARALLEL_LIMIT - 1) {
|
||||
const { setShowTips } = workflowStore.getState()
|
||||
setShowTips(t('workflow.common.parallelTip.limit', { num: PARALLEL_LIMIT }))
|
||||
return
|
||||
}
|
||||
setOpen(v => !v)
|
||||
}, [])
|
||||
}, [data._connectedSourceHandleIds])
|
||||
const handleSelect = useCallback((type: BlockEnum, toolDefaultValue?: ToolDefaultValue) => {
|
||||
handleNodeAdd(
|
||||
{
|
||||
@ -142,7 +154,7 @@ export const NodeSourceHandle = memo(({
|
||||
}, [handleNodeAdd, id, handleId])
|
||||
|
||||
useEffect(() => {
|
||||
if (notInitialWorkflow && data.type === BlockEnum.Start)
|
||||
if (notInitialWorkflow && data.type === BlockEnum.Start && !isChatMode)
|
||||
setOpen(true)
|
||||
}, [notInitialWorkflow, data.type])
|
||||
|
||||
|
@ -162,6 +162,8 @@ type Shape = {
|
||||
setControlPromptEditorRerenderKey: (controlPromptEditorRerenderKey: number) => void
|
||||
showImportDSLModal: boolean
|
||||
setShowImportDSLModal: (showImportDSLModal: boolean) => void
|
||||
showTips: string
|
||||
setShowTips: (showTips: string) => void
|
||||
}
|
||||
|
||||
export const createWorkflowStore = () => {
|
||||
@ -262,6 +264,8 @@ export const createWorkflowStore = () => {
|
||||
setControlPromptEditorRerenderKey: controlPromptEditorRerenderKey => set(() => ({ controlPromptEditorRerenderKey })),
|
||||
showImportDSLModal: false,
|
||||
setShowImportDSLModal: showImportDSLModal => set(() => ({ showImportDSLModal })),
|
||||
showTips: '',
|
||||
setShowTips: showTips => set(() => ({ showTips })),
|
||||
}))
|
||||
}
|
||||
|
||||
|
@ -87,6 +87,7 @@ const translation = {
|
||||
title: 'Drag',
|
||||
desc: ' to connect',
|
||||
},
|
||||
limit: 'Parallelism is limited to {{num}} branches.',
|
||||
},
|
||||
},
|
||||
env: {
|
||||
|
@ -87,6 +87,7 @@ const translation = {
|
||||
title: '拖拽',
|
||||
desc: '连接节点',
|
||||
},
|
||||
limit: '并行分支限制为 {{num}} 个',
|
||||
},
|
||||
},
|
||||
env: {
|
||||
|
Loading…
x
Reference in New Issue
Block a user