feat: knowledge pipeline (#25360)

Signed-off-by: -LAN- <laipz8200@outlook.com>
Co-authored-by: twwu <twwu@dify.ai>
Co-authored-by: crazywoola <100913391+crazywoola@users.noreply.github.com>
Co-authored-by: jyong <718720800@qq.com>
Co-authored-by: Wu Tianwei <30284043+WTW0313@users.noreply.github.com>
Co-authored-by: QuantumGhost <obelisk.reg+git@gmail.com>
Co-authored-by: lyzno1 <yuanyouhuilyz@gmail.com>
Co-authored-by: quicksand <quicksandzn@gmail.com>
Co-authored-by: Jyong <76649700+JohnJyong@users.noreply.github.com>
Co-authored-by: lyzno1 <92089059+lyzno1@users.noreply.github.com>
Co-authored-by: zxhlyh <jasonapring2015@outlook.com>
Co-authored-by: Yongtao Huang <yongtaoh2022@gmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Joel <iamjoel007@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: nite-knite <nkCoding@gmail.com>
Co-authored-by: Hanqing Zhao <sherry9277@gmail.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: Harry <xh001x@hotmail.com>
This commit is contained in:
-LAN-
2025-09-18 12:49:10 +08:00
committed by GitHub
parent 7dadb33003
commit 85cda47c70
1772 changed files with 102407 additions and 31710 deletions

View File

@@ -0,0 +1 @@
export const CUSTOM_DATA_SOURCE_EMPTY_NODE = 'custom-data-source-empty'

View File

@@ -0,0 +1,22 @@
import type { NodeDefault } from '../../types'
import type { DataSourceEmptyNodeType } from './types'
import { genNodeMetaData } from '@/app/components/workflow/utils'
import { BlockEnum } from '@/app/components/workflow/types'
const metaData = genNodeMetaData({
sort: -1,
type: BlockEnum.DataSourceEmpty,
isUndeletable: true,
isSingleton: true,
})
const nodeDefault: NodeDefault<DataSourceEmptyNodeType> = {
metaData,
defaultValue: {},
checkValid() {
return {
isValid: true,
}
},
}
export default nodeDefault

View File

@@ -0,0 +1,50 @@
import { useCallback } from 'react'
import { useStoreApi } from 'reactflow'
import { produce } from 'immer'
import type { OnSelectBlock } from '@/app/components/workflow/types'
import { generateNewNode } from '@/app/components/workflow/utils'
import { useNodesMetaData } from '@/app/components/workflow/hooks'
export const useReplaceDataSourceNode = (id: string) => {
const store = useStoreApi()
const { nodesMap: nodesMetaDataMap } = useNodesMetaData()
const handleReplaceNode = useCallback<OnSelectBlock>((
type,
toolDefaultValue,
) => {
const {
getNodes,
setNodes,
} = store.getState()
const nodes = getNodes()
const emptyNodeIndex = nodes.findIndex(node => node.id === id)
if (emptyNodeIndex < 0) return
const {
defaultValue,
} = nodesMetaDataMap![type]
const emptyNode = nodes[emptyNodeIndex]
const { newNode } = generateNewNode({
data: {
...(defaultValue as any),
...toolDefaultValue,
},
position: {
x: emptyNode.position.x,
y: emptyNode.position.y,
},
})
const newNodes = produce(nodes, (draft) => {
draft[emptyNodeIndex] = newNode
})
const newNodesWithoutTempNodes = produce(newNodes, (draft) => {
return draft.filter(node => !node.data._isTempNode)
})
setNodes(newNodesWithoutTempNodes)
}, [])
return {
handleReplaceNode,
}
}

View File

@@ -0,0 +1,74 @@
import {
memo,
useCallback,
} from 'react'
import { useTranslation } from 'react-i18next'
import type { NodeProps } from 'reactflow'
import { RiAddLine } from '@remixicon/react'
import cn from '@/utils/classnames'
import Button from '@/app/components/base/button'
import BlockSelector from '@/app/components/workflow/block-selector'
import { useReplaceDataSourceNode } from './hooks'
const DataSourceEmptyNode = ({ id, data }: NodeProps) => {
const { t } = useTranslation()
const { handleReplaceNode } = useReplaceDataSourceNode(id)
const renderTrigger = useCallback(() => {
return (
<Button
variant='primary'
className='w-full'
>
<RiAddLine className='mr-1 h-4 w-4' />
{t('workflow.nodes.dataSource.add')}
</Button>
)
}, [])
return (
<div
className={cn(
'relative flex rounded-2xl border',
'border-transparent',
)}
style={{
width: data.width,
height: data.height,
}}
>
<div className='absolute inset-[-2px] top-[-22px] z-[-1] rounded-[18px] bg-node-data-source-bg p-0.5 backdrop-blur-[6px]'>
<div className='system-2xs-semibold-uppercase flex h-5 items-center px-2.5 text-text-tertiary'>
{t('workflow.blocks.datasource')}
</div>
</div>
<div
className={cn(
'group relative shadow-xs',
'rounded-[15px] border border-transparent',
'w-[240px] bg-workflow-block-bg',
)}
>
<div className={cn(
'flex items-center rounded-t-2xl p-3',
)}>
<BlockSelector
asChild
onSelect={handleReplaceNode}
trigger={renderTrigger}
noBlocks
noTools
popupClassName='w-[320px]'
placement='bottom-start'
offset={{
mainAxis: 4,
crossAxis: 0,
}}
/>
</div>
</div>
</div>
)
}
export default memo(DataSourceEmptyNode)

View File

@@ -0,0 +1,3 @@
import type { CommonNodeType } from '@/app/components/workflow/types'
export type DataSourceEmptyNodeType = CommonNodeType