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

@@ -34,7 +34,7 @@ import {
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 { useHooksStore } from '../../hooks-store'
type GetAbortController = (abortController: AbortController) => void
type SendCallback = {
@@ -58,8 +58,8 @@ export const useChat = (
const taskIdRef = useRef('')
const [isResponding, setIsResponding] = useState(false)
const isRespondingRef = useRef(false)
const { appId } = useParams()
const invalidAllLastRun = useInvalidAllLastRun(appId as string)
const configsMap = useHooksStore(s => s.configsMap)
const invalidAllLastRun = useInvalidAllLastRun(configsMap?.flowType, configsMap?.flowId)
const { fetchInspectVars } = useSetWorkflowVarsWithValue()
const [suggestedQuestions, setSuggestQuestions] = useState<string[]>([])
const suggestedQuestionsAbortControllerRef = useRef<AbortController | null>(null)
@@ -296,7 +296,7 @@ export const useChat = (
},
async onCompleted(hasError?: boolean, errorMessage?: string) {
handleResponding(false)
fetchInspectVars()
fetchInspectVars({})
invalidAllLastRun()
if (hasError) {
@@ -466,7 +466,7 @@ export const useChat = (
if (current.execution_metadata) {
if (current.execution_metadata.agent_log) {
const currentLogIndex = current.execution_metadata.agent_log.findIndex(log => log.id === data.id)
const currentLogIndex = current.execution_metadata.agent_log.findIndex(log => log.message_id === data.message_id)
if (currentLogIndex > -1) {
current.execution_metadata.agent_log[currentLogIndex] = {
...current.execution_metadata.agent_log[currentLogIndex],

View File

@@ -1,17 +1,24 @@
import type { FC } from 'react'
import { useShallow } from 'zustand/react/shallow'
import { memo, useCallback, useEffect, useRef } from 'react'
import type { VersionHistoryPanelProps } from '@/app/components/workflow/panel/version-history-panel'
import { useShallow } from 'zustand/react/shallow'
import { useStore as useReactflow } from 'reactflow'
import { Panel as NodePanel } from '../nodes'
import { useStore } from '../store'
import EnvPanel from './env-panel'
import cn from '@/utils/classnames'
import dynamic from 'next/dynamic'
const VersionHistoryPanel = dynamic(() => import('@/app/components/workflow/panel/version-history-panel'), {
ssr: false,
})
export type PanelProps = {
components?: {
left?: React.ReactNode
right?: React.ReactNode
}
versionHistoryPanelProps?: VersionHistoryPanelProps
}
/**
@@ -60,6 +67,7 @@ const useResizeObserver = (
const Panel: FC<PanelProps> = ({
components,
versionHistoryPanelProps,
}) => {
const selectedNode = useReactflow(useShallow((s) => {
const nodes = s.getNodes()
@@ -127,8 +135,19 @@ const Panel: FC<PanelProps> = ({
className="relative"
ref={otherPanelRef}
>
{components?.right}
{showEnvPanel && <EnvPanel />}
{
components?.right
}
{
showWorkflowVersionHistoryPanel && (
<VersionHistoryPanel {...versionHistoryPanelProps} />
)
}
{
showEnvPanel && (
<EnvPanel />
)
}
</div>
</div>
)

View File

@@ -19,11 +19,11 @@ 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 { useFeatures } from '@/app/components/base/features/hooks'
import {
getProcessedInputs,
} from '@/app/components/base/chat/chat/utils'
import { useCheckInputsForms } from '@/app/components/base/chat/chat/check-input-forms-hooks'
import { useHooksStore } from '../hooks-store'
type Props = {
onRun: () => void
@@ -36,7 +36,7 @@ const InputsPanel = ({ onRun }: Props) => {
inputs: s.inputs,
setInputs: s.setInputs,
}))
const fileSettings = useFeatures(s => s.features.file)
const fileSettings = useHooksStore(s => s.configsMap?.fileSettings)
const nodes = useNodes<StartNodeType>()
const files = useStore(s => s.files)
const workflowRunningData = useStore(s => s.workflowRunningData)

View File

@@ -3,11 +3,13 @@ import type { WorkflowRunDetailResponse } from '@/models/log'
import Run from '../run'
import { useStore } from '../store'
import { useWorkflowUpdate } from '../hooks'
import { useHooksStore } from '../hooks-store'
import { formatWorkflowRunIdentifier } from '../utils'
const Record = () => {
const historyWorkflowData = useStore(s => s.historyWorkflowData)
const { handleUpdateWorkflowCanvas } = useWorkflowUpdate()
const getWorkflowRunAndTraceUrl = useHooksStore(s => s.getWorkflowRunAndTraceUrl)
const handleResultCallback = useCallback((res: WorkflowRunDetailResponse) => {
const graph = res.graph
@@ -24,7 +26,8 @@ const Record = () => {
{`Test Run${formatWorkflowRunIdentifier(historyWorkflowData?.finished_at)}`}
</div>
<Run
runID={historyWorkflowData?.id || ''}
runDetailUrl={getWorkflowRunAndTraceUrl(historyWorkflowData?.id).runUrl}
tracingListUrl={getWorkflowRunAndTraceUrl(historyWorkflowData?.id).traceUrl}
getResultCallback={handleResultCallback}
/>
</div>

View File

@@ -2,12 +2,14 @@ import { useMemo } from 'react'
import { useTranslation } from 'react-i18next'
import { VersionHistoryContextMenuOptions } from '../../../types'
import type { ContextMenuProps } from './index'
import { useStore } from '@/app/components/workflow/store'
const useContextMenu = (props: ContextMenuProps) => {
const {
isNamedVersion,
} = props
const { t } = useTranslation()
const pipelineId = useStore(s => s.pipelineId)
const deleteOperation = {
key: VersionHistoryContextMenuOptions.delete,
@@ -29,10 +31,11 @@ const useContextMenu = (props: ContextMenuProps) => {
key: VersionHistoryContextMenuOptions.edit,
name: t('workflow.versionHistory.nameThisVersion'),
},
{
// todo: pipeline support export specific version DSL
...(!pipelineId ? [{
key: VersionHistoryContextMenuOptions.exportDSL,
name: t('app.export'),
},
}] : []),
{
key: VersionHistoryContextMenuOptions.copyId,
name: t('workflow.versionHistory.copyId'),

View File

@@ -9,7 +9,6 @@ import { VersionHistoryContextMenuOptions, WorkflowVersionFilterOptions } from '
import VersionHistoryItem from './version-history-item'
import Filter from './filter'
import type { VersionHistory } from '@/types/workflow'
import { useStore as useAppStore } from '@/app/components/app/store'
import { useDeleteWorkflow, useInvalidAllLastRun, useResetWorkflowVersionHistory, useUpdateWorkflow, useWorkflowVersionHistory } from '@/service/use-workflow'
import Divider from '@/app/components/base/divider'
import Loading from './loading'
@@ -19,11 +18,23 @@ import RestoreConfirmModal from './restore-confirm-modal'
import DeleteConfirmModal from './delete-confirm-modal'
import VersionInfoModal from '@/app/components/app/app-publisher/version-info-modal'
import Toast from '@/app/components/base/toast'
import { useHooksStore } from '../../hooks-store'
const HISTORY_PER_PAGE = 10
const INITIAL_PAGE = 1
const VersionHistoryPanel = () => {
export type VersionHistoryPanelProps = {
getVersionListUrl?: string
deleteVersionUrl?: (versionId: string) => string
updateVersionUrl?: (versionId: string) => string
latestVersionId?: string
}
export const VersionHistoryPanel = ({
getVersionListUrl,
deleteVersionUrl,
updateVersionUrl,
latestVersionId,
}: VersionHistoryPanelProps) => {
const [filterValue, setFilterValue] = useState(WorkflowVersionFilterOptions.all)
const [isOnlyShowNamedVersions, setIsOnlyShowNamedVersions] = useState(false)
const [operatedItem, setOperatedItem] = useState<VersionHistory>()
@@ -34,12 +45,12 @@ const VersionHistoryPanel = () => {
const { handleSyncWorkflowDraft } = useNodesSyncDraft()
const { handleRestoreFromPublishedWorkflow, handleLoadBackupDraft } = useWorkflowRun()
const { handleExportDSL } = useDSL()
const appDetail = useAppStore.getState().appDetail
const setShowWorkflowVersionHistoryPanel = useStore(s => s.setShowWorkflowVersionHistoryPanel)
const currentVersion = useStore(s => s.currentVersion)
const setCurrentVersion = useStore(s => s.setCurrentVersion)
const userProfile = useAppContextSelector(s => s.userProfile)
const invalidAllLastRun = useInvalidAllLastRun(appDetail!.id)
const configsMap = useHooksStore(s => s.configsMap)
const invalidAllLastRun = useInvalidAllLastRun(configsMap?.flowType, configsMap?.flowId)
const {
deleteAllInspectVars,
} = workflowStore.getState()
@@ -51,7 +62,7 @@ const VersionHistoryPanel = () => {
hasNextPage,
isFetching,
} = useWorkflowVersionHistory({
appId: appDetail!.id,
url: getVersionListUrl || '',
initialPage: INITIAL_PAGE,
limit: HISTORY_PER_PAGE,
userId: filterValue === WorkflowVersionFilterOptions.onlyYours ? userProfile.id : '',
@@ -109,7 +120,7 @@ const VersionHistoryPanel = () => {
})
break
case VersionHistoryContextMenuOptions.exportDSL:
handleExportDSL(false, item.id)
handleExportDSL?.(false, item.id)
break
}
}, [t, handleExportDSL])
@@ -128,7 +139,7 @@ const VersionHistoryPanel = () => {
}
}, [])
const resetWorkflowVersionHistory = useResetWorkflowVersionHistory(appDetail!.id)
const resetWorkflowVersionHistory = useResetWorkflowVersionHistory()
const handleRestore = useCallback((item: VersionHistory) => {
setShowWorkflowVersionHistoryPanel(false)
@@ -156,10 +167,10 @@ const VersionHistoryPanel = () => {
})
}, [setShowWorkflowVersionHistoryPanel, handleRestoreFromPublishedWorkflow, workflowStore, handleSyncWorkflowDraft, deleteAllInspectVars, invalidAllLastRun, t, resetWorkflowVersionHistory])
const { mutateAsync: deleteWorkflow } = useDeleteWorkflow(appDetail!.id)
const { mutateAsync: deleteWorkflow } = useDeleteWorkflow()
const handleDelete = useCallback(async (id: string) => {
await deleteWorkflow(id, {
await deleteWorkflow(deleteVersionUrl?.(id) || '', {
onSuccess: () => {
setDeleteConfirmOpen(false)
Toast.notify({
@@ -180,14 +191,14 @@ const VersionHistoryPanel = () => {
setDeleteConfirmOpen(false)
},
})
}, [deleteWorkflow, t, resetWorkflowVersionHistory, deleteAllInspectVars, invalidAllLastRun])
}, [deleteWorkflow, t, resetWorkflowVersionHistory, deleteAllInspectVars, invalidAllLastRun, deleteVersionUrl])
const { mutateAsync: updateWorkflow } = useUpdateWorkflow(appDetail!.id)
const { mutateAsync: updateWorkflow } = useUpdateWorkflow()
const handleUpdateWorkflow = useCallback(async (params: { id?: string, title: string, releaseNotes: string }) => {
const { id, ...rest } = params
await updateWorkflow({
workflowId: id!,
url: updateVersionUrl?.(id || '') || '',
...rest,
}, {
onSuccess: () => {
@@ -208,7 +219,7 @@ const VersionHistoryPanel = () => {
setEditModalOpen(false)
},
})
}, [t, updateWorkflow, resetWorkflowVersionHistory])
}, [t, updateWorkflow, resetWorkflowVersionHistory, updateVersionUrl])
return (
<div className='flex h-full w-[268px] flex-col rounded-l-2xl border-y-[0.5px] border-l-[0.5px] border-components-panel-border bg-components-panel-bg shadow-xl shadow-shadow-shadow-5'>
@@ -243,7 +254,7 @@ const VersionHistoryPanel = () => {
key={item.id}
item={item}
currentVersion={currentVersion}
latestVersionId={appDetail!.workflow!.id}
latestVersionId={latestVersionId || ''}
onClick={handleVersionClick}
handleClickMenuItem={handleClickMenuItem.bind(null, item)}
isLast={isLast}

View File

@@ -184,7 +184,12 @@ const WorkflowPreview = () => {
{currentTab === 'DETAIL' && (
<ResultPanel
inputs={workflowRunningData?.result?.inputs}
inputs_truncated={workflowRunningData?.result?.inputs_truncated}
process_data={workflowRunningData?.result?.process_data}
process_data_truncated={workflowRunningData?.result?.process_data_truncated}
outputs={workflowRunningData?.result?.outputs}
outputs_truncated={workflowRunningData?.result?.outputs_truncated}
outputs_full_content={workflowRunningData?.result?.outputs_full_content}
status={workflowRunningData?.result?.status || ''}
error={workflowRunningData?.result?.error}
elapsed_time={workflowRunningData?.result?.elapsed_time}