mirror of
https://github.com/langgenius/dify.git
synced 2026-04-24 17:16:37 +08:00
chore: format
This commit is contained in:
parent
95da3a4cf1
commit
c23fe3b67f
@ -202,7 +202,7 @@ const ViewHistory = ({
|
|||||||
{`Test ${isChatMode ? 'Chat' : 'Run'}#${item.sequence_number}`}
|
{`Test ${isChatMode ? 'Chat' : 'Run'}#${item.sequence_number}`}
|
||||||
</div>
|
</div>
|
||||||
<div className='flex items-center text-xs text-gray-500 leading-[18px]'>
|
<div className='flex items-center text-xs text-gray-500 leading-[18px]'>
|
||||||
{item.created_by_account.name} · {formatTimeFromNow((item.finished_at || item.created_at) * 1000)}
|
{item.created_by_account?.name} · {formatTimeFromNow((item.finished_at || item.created_at) * 1000)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -61,7 +61,7 @@ const RunPanel: FC<RunProps> = ({ hideResult, activeTab = 'RESULT', runID, getRe
|
|||||||
const { data: nodeList } = await fetchTracingList({
|
const { data: nodeList } = await fetchTracingList({
|
||||||
url: `/apps/${appID}/workflow-runs/${runID}/node-executions`,
|
url: `/apps/${appID}/workflow-runs/${runID}/node-executions`,
|
||||||
})
|
})
|
||||||
setList(formatNodeList(nodeList))
|
setList(formatNodeList(nodeList, t))
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch (err) {
|
||||||
notify({
|
notify({
|
||||||
|
|||||||
@ -11,13 +11,9 @@ import {
|
|||||||
RiArrowDownSLine,
|
RiArrowDownSLine,
|
||||||
RiMenu4Line,
|
RiMenu4Line,
|
||||||
} from '@remixicon/react'
|
} from '@remixicon/react'
|
||||||
import { useTranslation } from 'react-i18next'
|
|
||||||
import { useLogs } from './hooks'
|
import { useLogs } from './hooks'
|
||||||
import NodePanel from './node'
|
import NodePanel from './node'
|
||||||
import SpecialResultPanel from './special-result-panel'
|
import SpecialResultPanel from './special-result-panel'
|
||||||
import {
|
|
||||||
BlockEnum,
|
|
||||||
} from '@/app/components/workflow/types'
|
|
||||||
import type { NodeTracing } from '@/types/workflow'
|
import type { NodeTracing } from '@/types/workflow'
|
||||||
|
|
||||||
type TracingPanelProps = {
|
type TracingPanelProps = {
|
||||||
@ -27,145 +23,14 @@ type TracingPanelProps = {
|
|||||||
hideNodeProcessDetail?: boolean
|
hideNodeProcessDetail?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type TracingNodeProps = {
|
|
||||||
id: string
|
|
||||||
uniqueId: string
|
|
||||||
isParallel: boolean
|
|
||||||
data: NodeTracing | null
|
|
||||||
children: TracingNodeProps[]
|
|
||||||
parallelTitle?: string
|
|
||||||
branchTitle?: string
|
|
||||||
hideNodeInfo?: boolean
|
|
||||||
hideNodeProcessDetail?: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
function buildLogTree(nodes: NodeTracing[], t: (key: string) => string): TracingNodeProps[] {
|
|
||||||
const rootNodes: TracingNodeProps[] = []
|
|
||||||
const parallelStacks: { [key: string]: TracingNodeProps } = {}
|
|
||||||
const levelCounts: { [key: string]: number } = {}
|
|
||||||
const parallelChildCounts: { [key: string]: Set<string> } = {}
|
|
||||||
let uniqueIdCounter = 0
|
|
||||||
const getUniqueId = () => {
|
|
||||||
uniqueIdCounter++
|
|
||||||
return `unique-${uniqueIdCounter}`
|
|
||||||
}
|
|
||||||
|
|
||||||
const getParallelTitle = (parentId: string | null): string => {
|
|
||||||
const levelKey = parentId || 'root'
|
|
||||||
if (!levelCounts[levelKey])
|
|
||||||
levelCounts[levelKey] = 0
|
|
||||||
|
|
||||||
levelCounts[levelKey]++
|
|
||||||
|
|
||||||
const parentTitle = parentId ? parallelStacks[parentId]?.parallelTitle : ''
|
|
||||||
const levelNumber = parentTitle ? Number.parseInt(parentTitle.split('-')[1]) + 1 : 1
|
|
||||||
const letter = parallelChildCounts[levelKey]?.size > 1 ? String.fromCharCode(64 + levelCounts[levelKey]) : ''
|
|
||||||
return `${t('workflow.common.parallel')}-${levelNumber}${letter}`
|
|
||||||
}
|
|
||||||
|
|
||||||
const getBranchTitle = (parentId: string | null, branchNum: number): string => {
|
|
||||||
const levelKey = parentId || 'root'
|
|
||||||
const parentTitle = parentId ? parallelStacks[parentId]?.parallelTitle : ''
|
|
||||||
const levelNumber = parentTitle ? Number.parseInt(parentTitle.split('-')[1]) + 1 : 1
|
|
||||||
const letter = parallelChildCounts[levelKey]?.size > 1 ? String.fromCharCode(64 + levelCounts[levelKey]) : ''
|
|
||||||
const branchLetter = String.fromCharCode(64 + branchNum)
|
|
||||||
return `${t('workflow.common.branch')}-${levelNumber}${letter}-${branchLetter}`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Count parallel children (for figuring out if we need to use letters)
|
|
||||||
for (const node of nodes) {
|
|
||||||
const parent_parallel_id = node.parent_parallel_id ?? node.execution_metadata?.parent_parallel_id ?? null
|
|
||||||
const parallel_id = node.parallel_id ?? node.execution_metadata?.parallel_id ?? null
|
|
||||||
|
|
||||||
if (parallel_id) {
|
|
||||||
const parentKey = parent_parallel_id || 'root'
|
|
||||||
if (!parallelChildCounts[parentKey])
|
|
||||||
parallelChildCounts[parentKey] = new Set()
|
|
||||||
|
|
||||||
parallelChildCounts[parentKey].add(parallel_id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const node of nodes) {
|
|
||||||
const parallel_id = node.parallel_id ?? node.execution_metadata?.parallel_id ?? null
|
|
||||||
const parent_parallel_id = node.parent_parallel_id ?? node.execution_metadata?.parent_parallel_id ?? null
|
|
||||||
const parallel_start_node_id = node.parallel_start_node_id ?? node.execution_metadata?.parallel_start_node_id ?? null
|
|
||||||
const parent_parallel_start_node_id = node.parent_parallel_start_node_id ?? node.execution_metadata?.parent_parallel_start_node_id ?? null
|
|
||||||
|
|
||||||
if (!parallel_id || node.node_type === BlockEnum.End) {
|
|
||||||
rootNodes.push({
|
|
||||||
id: node.id,
|
|
||||||
uniqueId: getUniqueId(),
|
|
||||||
isParallel: false,
|
|
||||||
data: node,
|
|
||||||
children: [],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!parallelStacks[parallel_id]) {
|
|
||||||
const newParallelGroup: TracingNodeProps = {
|
|
||||||
id: parallel_id,
|
|
||||||
uniqueId: getUniqueId(),
|
|
||||||
isParallel: true,
|
|
||||||
data: null,
|
|
||||||
children: [],
|
|
||||||
parallelTitle: '',
|
|
||||||
}
|
|
||||||
parallelStacks[parallel_id] = newParallelGroup
|
|
||||||
|
|
||||||
if (parent_parallel_id && parallelStacks[parent_parallel_id]) {
|
|
||||||
const sameBranchIndex = parallelStacks[parent_parallel_id].children.findLastIndex(c =>
|
|
||||||
c.data?.execution_metadata?.parallel_start_node_id === parent_parallel_start_node_id || c.data?.parallel_start_node_id === parent_parallel_start_node_id,
|
|
||||||
)
|
|
||||||
parallelStacks[parent_parallel_id].children.splice(sameBranchIndex + 1, 0, newParallelGroup)
|
|
||||||
newParallelGroup.parallelTitle = getParallelTitle(parent_parallel_id)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
newParallelGroup.parallelTitle = getParallelTitle(parent_parallel_id)
|
|
||||||
rootNodes.push(newParallelGroup)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const branchTitle = parallel_start_node_id === node.node_id ? getBranchTitle(parent_parallel_id, parallelStacks[parallel_id].children.length + 1) : ''
|
|
||||||
if (branchTitle) {
|
|
||||||
parallelStacks[parallel_id].children.push({
|
|
||||||
id: node.id,
|
|
||||||
uniqueId: getUniqueId(),
|
|
||||||
isParallel: false,
|
|
||||||
data: node,
|
|
||||||
children: [],
|
|
||||||
branchTitle,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
let sameBranchIndex = parallelStacks[parallel_id].children.findLastIndex(c =>
|
|
||||||
c.data?.execution_metadata?.parallel_start_node_id === parallel_start_node_id || c.data?.parallel_start_node_id === parallel_start_node_id,
|
|
||||||
)
|
|
||||||
if (parallelStacks[parallel_id].children[sameBranchIndex + 1]?.isParallel)
|
|
||||||
sameBranchIndex++
|
|
||||||
|
|
||||||
parallelStacks[parallel_id].children.splice(sameBranchIndex + 1, 0, {
|
|
||||||
id: node.id,
|
|
||||||
uniqueId: getUniqueId(),
|
|
||||||
isParallel: false,
|
|
||||||
data: node,
|
|
||||||
children: [],
|
|
||||||
branchTitle,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rootNodes
|
|
||||||
}
|
|
||||||
|
|
||||||
const TracingPanel: FC<TracingPanelProps> = ({
|
const TracingPanel: FC<TracingPanelProps> = ({
|
||||||
list,
|
list,
|
||||||
className,
|
className,
|
||||||
hideNodeInfo = false,
|
hideNodeInfo = false,
|
||||||
hideNodeProcessDetail = false,
|
hideNodeProcessDetail = false,
|
||||||
}) => {
|
}) => {
|
||||||
const { t } = useTranslation()
|
const treeNodes = list
|
||||||
const treeNodes = buildLogTree(list, t)
|
console.log(treeNodes)
|
||||||
const [collapsedNodes, setCollapsedNodes] = useState<Set<string>>(new Set())
|
const [collapsedNodes, setCollapsedNodes] = useState<Set<string>>(new Set())
|
||||||
const [hoveredParallel, setHoveredParallel] = useState<string | null>(null)
|
const [hoveredParallel, setHoveredParallel] = useState<string | null>(null)
|
||||||
|
|
||||||
@ -219,13 +84,16 @@ const TracingPanel: FC<TracingPanelProps> = ({
|
|||||||
setAgentResultList,
|
setAgentResultList,
|
||||||
} = useLogs()
|
} = useLogs()
|
||||||
|
|
||||||
const renderNode = (node: TracingNodeProps) => {
|
|
||||||
if (node.isParallel) {
|
const renderNode = (node: NodeTracing) => {
|
||||||
|
const isParallelFirstNode = !!node.parallelDetail?.isParallelStartNode
|
||||||
|
if (isParallelFirstNode) {
|
||||||
|
const parallelDetail = node.parallelDetail!
|
||||||
const isCollapsed = collapsedNodes.has(node.id)
|
const isCollapsed = collapsedNodes.has(node.id)
|
||||||
const isHovered = hoveredParallel === node.id
|
const isHovered = hoveredParallel === node.id
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
key={node.uniqueId}
|
key={node.id}
|
||||||
className="ml-4 mb-2 relative"
|
className="ml-4 mb-2 relative"
|
||||||
data-parallel-id={node.id}
|
data-parallel-id={node.id}
|
||||||
onMouseEnter={() => handleParallelMouseEnter(node.id)}
|
onMouseEnter={() => handleParallelMouseEnter(node.id)}
|
||||||
@ -242,7 +110,7 @@ const TracingPanel: FC<TracingPanelProps> = ({
|
|||||||
{isHovered ? <RiArrowDownSLine className="w-3 h-3" /> : <RiMenu4Line className="w-3 h-3 text-text-tertiary" />}
|
{isHovered ? <RiArrowDownSLine className="w-3 h-3" /> : <RiMenu4Line className="w-3 h-3 text-text-tertiary" />}
|
||||||
</button>
|
</button>
|
||||||
<div className="system-xs-semibold-uppercase text-text-secondary flex items-center">
|
<div className="system-xs-semibold-uppercase text-text-secondary flex items-center">
|
||||||
<span>{node.parallelTitle}</span>
|
<span>{parallelDetail.parallelTitle}</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className="mx-2 grow h-px bg-divider-subtle"
|
className="mx-2 grow h-px bg-divider-subtle"
|
||||||
@ -254,7 +122,7 @@ const TracingPanel: FC<TracingPanelProps> = ({
|
|||||||
'absolute top-0 bottom-0 left-[5px] w-[2px]',
|
'absolute top-0 bottom-0 left-[5px] w-[2px]',
|
||||||
isHovered ? 'bg-text-accent-secondary' : 'bg-divider-subtle',
|
isHovered ? 'bg-text-accent-secondary' : 'bg-divider-subtle',
|
||||||
)}></div>
|
)}></div>
|
||||||
{node.children.map(renderNode)}
|
{parallelDetail.children!.map(renderNode)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@ -262,12 +130,12 @@ const TracingPanel: FC<TracingPanelProps> = ({
|
|||||||
else {
|
else {
|
||||||
const isHovered = hoveredParallel === node.id
|
const isHovered = hoveredParallel === node.id
|
||||||
return (
|
return (
|
||||||
<div key={node.uniqueId}>
|
<div key={node.id}>
|
||||||
<div className={cn('pl-4 -mb-1.5 system-2xs-medium-uppercase', isHovered ? 'text-text-tertiary' : 'text-text-quaternary')}>
|
<div className={cn('pl-4 -mb-1.5 system-2xs-medium-uppercase', isHovered ? 'text-text-tertiary' : 'text-text-quaternary')}>
|
||||||
{node.branchTitle}
|
{node?.parallelDetail?.branchTitle}
|
||||||
</div>
|
</div>
|
||||||
<NodePanel
|
<NodePanel
|
||||||
nodeInfo={node.data!}
|
nodeInfo={node!}
|
||||||
onShowIterationDetail={handleShowIterationResultList}
|
onShowIterationDetail={handleShowIterationResultList}
|
||||||
onShowRetryDetail={handleShowRetryResultList}
|
onShowRetryDetail={handleShowRetryResultList}
|
||||||
onShowAgentResultList={setAgentResultList}
|
onShowAgentResultList={setAgentResultList}
|
||||||
|
|||||||
@ -1,15 +1,22 @@
|
|||||||
import type { NodeTracing } from '@/types/workflow'
|
import type { NodeTracing } from '@/types/workflow'
|
||||||
import formatIterationNode from './iteration'
|
import formatIterationNode from './iteration'
|
||||||
|
import formatParallelNode from './parallel'
|
||||||
import formatRetryNode from './retry'
|
import formatRetryNode from './retry'
|
||||||
import formatAgentNode from './agent'
|
import formatAgentNode from './agent'
|
||||||
|
|
||||||
const formatToTracingNodeList = (list: NodeTracing[]) => {
|
const formatToTracingNodeList = (list: NodeTracing[], t: any) => {
|
||||||
const allItems = [...list].reverse()
|
const allItems = [...list].reverse()
|
||||||
const formattedIterationList = formatIterationNode(allItems)
|
/*
|
||||||
const formattedRetryList = formatRetryNode(formattedIterationList)
|
* First handle not change list structure node
|
||||||
const formattedAgentList = formatAgentNode(formattedRetryList)
|
* Because Handle struct node will put the node in different
|
||||||
|
*/
|
||||||
|
const formattedAgentList = formatAgentNode(allItems)
|
||||||
|
const formattedRetryList = formatRetryNode(formattedAgentList) // retry one node
|
||||||
|
// would change the structure of the list. Iteration and parallel can include each other.
|
||||||
|
const formattedIterationList = formatIterationNode(formattedRetryList)
|
||||||
|
const formattedParallelList = formatParallelNode(formattedIterationList, t)
|
||||||
|
|
||||||
const result = formattedAgentList
|
const result = formattedParallelList
|
||||||
// console.log(allItems)
|
// console.log(allItems)
|
||||||
// console.log(result)
|
// console.log(result)
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,132 @@
|
|||||||
|
import type { NodeTracing } from '@/types/workflow'
|
||||||
|
|
||||||
|
type TracingNodeProps = {
|
||||||
|
id: string
|
||||||
|
uniqueId: string
|
||||||
|
isParallel: boolean
|
||||||
|
data: NodeTracing | null
|
||||||
|
children: TracingNodeProps[]
|
||||||
|
parallelTitle?: string
|
||||||
|
branchTitle?: string
|
||||||
|
hideNodeInfo?: boolean
|
||||||
|
hideNodeProcessDetail?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildLogTree(nodes: NodeTracing[], t: (key: string) => string): TracingNodeProps[] {
|
||||||
|
const rootNodes: TracingNodeProps[] = []
|
||||||
|
const parallelStacks: { [key: string]: TracingNodeProps } = {}
|
||||||
|
const levelCounts: { [key: string]: number } = {}
|
||||||
|
const parallelChildCounts: { [key: string]: Set<string> } = {}
|
||||||
|
let uniqueIdCounter = 0
|
||||||
|
const getUniqueId = () => {
|
||||||
|
uniqueIdCounter++
|
||||||
|
return `unique-${uniqueIdCounter}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const getParallelTitle = (parentId: string | null): string => {
|
||||||
|
const levelKey = parentId || 'root'
|
||||||
|
if (!levelCounts[levelKey])
|
||||||
|
levelCounts[levelKey] = 0
|
||||||
|
|
||||||
|
levelCounts[levelKey]++
|
||||||
|
|
||||||
|
const parentTitle = parentId ? parallelStacks[parentId]?.parallelTitle : ''
|
||||||
|
const levelNumber = parentTitle ? Number.parseInt(parentTitle.split('-')[1]) + 1 : 1
|
||||||
|
const letter = parallelChildCounts[levelKey]?.size > 1 ? String.fromCharCode(64 + levelCounts[levelKey]) : ''
|
||||||
|
return `${t('workflow.common.parallel')}-${levelNumber}${letter}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const getBranchTitle = (parentId: string | null, branchNum: number): string => {
|
||||||
|
const levelKey = parentId || 'root'
|
||||||
|
const parentTitle = parentId ? parallelStacks[parentId]?.parallelTitle : ''
|
||||||
|
const levelNumber = parentTitle ? Number.parseInt(parentTitle.split('-')[1]) + 1 : 1
|
||||||
|
const letter = parallelChildCounts[levelKey]?.size > 1 ? String.fromCharCode(64 + levelCounts[levelKey]) : ''
|
||||||
|
const branchLetter = String.fromCharCode(64 + branchNum)
|
||||||
|
return `${t('workflow.common.branch')}-${levelNumber}${letter}-${branchLetter}`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count parallel children (for figuring out if we need to use letters)
|
||||||
|
for (const node of nodes) {
|
||||||
|
const parent_parallel_id = node.parent_parallel_id ?? node.execution_metadata?.parent_parallel_id ?? null
|
||||||
|
const parallel_id = node.parallel_id ?? node.execution_metadata?.parallel_id ?? null
|
||||||
|
|
||||||
|
if (parallel_id) {
|
||||||
|
const parentKey = parent_parallel_id || 'root'
|
||||||
|
if (!parallelChildCounts[parentKey])
|
||||||
|
parallelChildCounts[parentKey] = new Set()
|
||||||
|
|
||||||
|
parallelChildCounts[parentKey].add(parallel_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const node of nodes) {
|
||||||
|
const parallel_id = node.parallel_id ?? node.execution_metadata?.parallel_id ?? null
|
||||||
|
const parent_parallel_id = node.parent_parallel_id ?? node.execution_metadata?.parent_parallel_id ?? null
|
||||||
|
const parallel_start_node_id = node.parallel_start_node_id ?? node.execution_metadata?.parallel_start_node_id ?? null
|
||||||
|
const parent_parallel_start_node_id = node.parent_parallel_start_node_id ?? node.execution_metadata?.parent_parallel_start_node_id ?? null
|
||||||
|
|
||||||
|
if (!parallel_id || node.node_type === BlockEnum.End) {
|
||||||
|
rootNodes.push({
|
||||||
|
id: node.id,
|
||||||
|
uniqueId: getUniqueId(),
|
||||||
|
isParallel: false,
|
||||||
|
data: node,
|
||||||
|
children: [],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!parallelStacks[parallel_id]) {
|
||||||
|
const newParallelGroup: TracingNodeProps = {
|
||||||
|
id: parallel_id,
|
||||||
|
uniqueId: getUniqueId(),
|
||||||
|
isParallel: true,
|
||||||
|
data: null,
|
||||||
|
children: [],
|
||||||
|
parallelTitle: '',
|
||||||
|
}
|
||||||
|
parallelStacks[parallel_id] = newParallelGroup
|
||||||
|
|
||||||
|
if (parent_parallel_id && parallelStacks[parent_parallel_id]) {
|
||||||
|
const sameBranchIndex = parallelStacks[parent_parallel_id].children.findLastIndex(c =>
|
||||||
|
c.data?.execution_metadata?.parallel_start_node_id === parent_parallel_start_node_id || c.data?.parallel_start_node_id === parent_parallel_start_node_id,
|
||||||
|
)
|
||||||
|
parallelStacks[parent_parallel_id].children.splice(sameBranchIndex + 1, 0, newParallelGroup)
|
||||||
|
newParallelGroup.parallelTitle = getParallelTitle(parent_parallel_id)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
newParallelGroup.parallelTitle = getParallelTitle(parent_parallel_id)
|
||||||
|
rootNodes.push(newParallelGroup)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const branchTitle = parallel_start_node_id === node.node_id ? getBranchTitle(parent_parallel_id, parallelStacks[parallel_id].children.length + 1) : ''
|
||||||
|
if (branchTitle) {
|
||||||
|
parallelStacks[parallel_id].children.push({
|
||||||
|
id: node.id,
|
||||||
|
uniqueId: getUniqueId(),
|
||||||
|
isParallel: false,
|
||||||
|
data: node,
|
||||||
|
children: [],
|
||||||
|
branchTitle,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let sameBranchIndex = parallelStacks[parallel_id].children.findLastIndex(c =>
|
||||||
|
c.data?.execution_metadata?.parallel_start_node_id === parallel_start_node_id || c.data?.parallel_start_node_id === parallel_start_node_id,
|
||||||
|
)
|
||||||
|
if (parallelStacks[parallel_id].children[sameBranchIndex + 1]?.isParallel)
|
||||||
|
sameBranchIndex++
|
||||||
|
|
||||||
|
parallelStacks[parallel_id].children.splice(sameBranchIndex + 1, 0, {
|
||||||
|
id: node.id,
|
||||||
|
uniqueId: getUniqueId(),
|
||||||
|
isParallel: false,
|
||||||
|
data: node,
|
||||||
|
children: [],
|
||||||
|
branchTitle,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rootNodes
|
||||||
|
}
|
||||||
@ -0,0 +1,127 @@
|
|||||||
|
import { BlockEnum } from '@/app/components/workflow/types'
|
||||||
|
import type { NodeTracing } from '@/types/workflow'
|
||||||
|
|
||||||
|
function addTitle({
|
||||||
|
list, level, parallelNumRecord,
|
||||||
|
}: {
|
||||||
|
list: NodeTracing[], level: number, parallelNumRecord: Record<string, number>
|
||||||
|
}, t: any) {
|
||||||
|
let branchIndex = 0
|
||||||
|
list.forEach((node) => {
|
||||||
|
const parallel_id = node.parallel_id ?? node.execution_metadata?.parallel_id ?? null
|
||||||
|
const parallel_start_node_id = node.parallel_start_node_id ?? node.execution_metadata?.parallel_start_node_id ?? null
|
||||||
|
|
||||||
|
const isNotInParallel = !parallel_id || node.node_type === BlockEnum.End
|
||||||
|
if (isNotInParallel)
|
||||||
|
return
|
||||||
|
|
||||||
|
const isParallelStartNode = node.parallelDetail?.isParallelStartNode
|
||||||
|
if (isParallelStartNode)
|
||||||
|
parallelNumRecord.num++
|
||||||
|
|
||||||
|
const letter = parallelNumRecord.num > 1 ? String.fromCharCode(64 + level) : ''
|
||||||
|
const parallelLevelInfo = `${parallelNumRecord.num}${letter}`
|
||||||
|
|
||||||
|
if (isParallelStartNode) {
|
||||||
|
node.parallelDetail!.isParallelStartNode = true
|
||||||
|
node.parallelDetail!.parallelTitle = `${t('workflow.common.parallel')}-${parallelLevelInfo}`
|
||||||
|
}
|
||||||
|
|
||||||
|
const isBrachStartNode = parallel_start_node_id === node.node_id
|
||||||
|
if (isBrachStartNode) {
|
||||||
|
branchIndex++
|
||||||
|
const branchLetter = String.fromCharCode(64 + branchIndex)
|
||||||
|
if (!node.parallelDetail) {
|
||||||
|
node.parallelDetail = {
|
||||||
|
branchTitle: '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node.parallelDetail!.branchTitle = `${t('workflow.common.branch')}-${parallelLevelInfo}-${branchLetter}`
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.parallelDetail?.children && node.parallelDetail.children.length > 0) {
|
||||||
|
addTitle({
|
||||||
|
list: node.parallelDetail.children,
|
||||||
|
level: level + 1,
|
||||||
|
parallelNumRecord,
|
||||||
|
}, t)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// list => group by parallel_id(parallel tree).
|
||||||
|
const format = (list: NodeTracing[], t: any): NodeTracing[] => {
|
||||||
|
const result: NodeTracing[] = [...list]
|
||||||
|
const parallelFirstNodeMap: Record<string, string> = {}
|
||||||
|
// list to tree by parent_parallel_start_node_id and parallel_start_node_id
|
||||||
|
result.forEach((node) => {
|
||||||
|
const parallel_id = node.parallel_id ?? node.execution_metadata?.parallel_id ?? null
|
||||||
|
const parent_parallel_id = node.parent_parallel_id ?? node.execution_metadata?.parent_parallel_id ?? null
|
||||||
|
const parent_parallel_start_node_id = node.parent_parallel_start_node_id ?? node.execution_metadata?.parent_parallel_start_node_id ?? null
|
||||||
|
const isNotInParallel = !parallel_id || node.node_type === BlockEnum.End
|
||||||
|
if (isNotInParallel)
|
||||||
|
return
|
||||||
|
|
||||||
|
const isParallelStartNode = !parallelFirstNodeMap[parallel_id]
|
||||||
|
if (isParallelStartNode) {
|
||||||
|
const selfNode = { ...node }
|
||||||
|
node.parallelDetail = {
|
||||||
|
isParallelStartNode: true,
|
||||||
|
children: [selfNode],
|
||||||
|
}
|
||||||
|
parallelFirstNodeMap[parallel_id] = node.node_id
|
||||||
|
const isRootLevel = !parent_parallel_id
|
||||||
|
if (isRootLevel)
|
||||||
|
return
|
||||||
|
|
||||||
|
const parentParallelStartNode = result.find(item => item.node_id === parent_parallel_start_node_id)
|
||||||
|
// append to parent parallel start node
|
||||||
|
if (parentParallelStartNode) {
|
||||||
|
if (!parentParallelStartNode?.parallelDetail) {
|
||||||
|
parentParallelStartNode!.parallelDetail = {
|
||||||
|
children: [],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (parentParallelStartNode!.parallelDetail.children)
|
||||||
|
parentParallelStartNode!.parallelDetail.children.push(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// append to parallel start node
|
||||||
|
const parallelStartNode = result.find(item => item.node_id === parallelFirstNodeMap[parallel_id])
|
||||||
|
if (parallelStartNode && parallelStartNode.parallelDetail && parallelStartNode!.parallelDetail!.children)
|
||||||
|
parallelStartNode!.parallelDetail!.children.push(node)
|
||||||
|
})
|
||||||
|
|
||||||
|
const filteredInParallelSubNodes = result.filter((node) => {
|
||||||
|
const parallel_id = node.parallel_id ?? node.execution_metadata?.parallel_id ?? null
|
||||||
|
const isNotInParallel = !parallel_id || node.node_type === BlockEnum.End
|
||||||
|
if (isNotInParallel)
|
||||||
|
return true
|
||||||
|
|
||||||
|
const parent_parallel_id = node.parent_parallel_id ?? node.execution_metadata?.parent_parallel_id ?? null
|
||||||
|
|
||||||
|
if (parent_parallel_id)
|
||||||
|
return false
|
||||||
|
|
||||||
|
const isParallelStartNode = node.parallelDetail?.isParallelStartNode
|
||||||
|
if (!isParallelStartNode)
|
||||||
|
return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
|
||||||
|
const parallelNumRecord: Record<string, number> = {
|
||||||
|
num: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
addTitle({
|
||||||
|
list: filteredInParallelSubNodes,
|
||||||
|
level: 1,
|
||||||
|
parallelNumRecord,
|
||||||
|
}, t)
|
||||||
|
|
||||||
|
return filteredInParallelSubNodes
|
||||||
|
}
|
||||||
|
export default format
|
||||||
@ -68,12 +68,18 @@ export type NodeTracing = {
|
|||||||
expand?: boolean // for UI
|
expand?: boolean // for UI
|
||||||
details?: NodeTracing[][] // iteration detail
|
details?: NodeTracing[][] // iteration detail
|
||||||
retryDetail?: NodeTracing[] // retry detail
|
retryDetail?: NodeTracing[] // retry detail
|
||||||
agentLog?: AgentLogItemWithChildren[]
|
retry_index?: number
|
||||||
|
parallelDetail?: { // parallel detail. if is in parallel, this field will be set
|
||||||
|
isParallelStartNode?: boolean
|
||||||
|
parallelTitle?: string
|
||||||
|
branchTitle?: string
|
||||||
|
children?: NodeTracing[]
|
||||||
|
}
|
||||||
parallel_id?: string
|
parallel_id?: string
|
||||||
parallel_start_node_id?: string
|
parallel_start_node_id?: string
|
||||||
parent_parallel_id?: string
|
parent_parallel_id?: string
|
||||||
parent_parallel_start_node_id?: string
|
parent_parallel_start_node_id?: string
|
||||||
retry_index?: number
|
agentLog?: AgentLogItemWithChildren[] // agent log
|
||||||
}
|
}
|
||||||
|
|
||||||
export type FetchWorkflowDraftResponse = {
|
export type FetchWorkflowDraftResponse = {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user