Feat/loop break node (#17268)

This commit is contained in:
zxhlyh
2025-04-01 16:52:07 +08:00
committed by GitHub
parent 627a9e2ce1
commit 713902dc47
64 changed files with 1397 additions and 139 deletions

View File

@@ -8,6 +8,7 @@ import type {
AgentLogItemWithChildren,
IterationDurationMap,
LoopDurationMap,
LoopVariableMap,
NodeTracing,
} from '@/types/workflow'
@@ -40,10 +41,12 @@ export const useLogs = () => {
}] = useBoolean(false)
const [loopResultList, setLoopResultList] = useState<NodeTracing[][]>([])
const [loopResultDurationMap, setLoopResultDurationMap] = useState<LoopDurationMap>({})
const handleShowLoopResultList = useCallback((detail: NodeTracing[][], loopDurationMap: LoopDurationMap) => {
const [loopResultVariableMap, setLoopResultVariableMap] = useState<Record<string, any>>({})
const handleShowLoopResultList = useCallback((detail: NodeTracing[][], loopDurationMap: LoopDurationMap, loopVariableMap: LoopVariableMap) => {
setShowLoopingDetailTrue()
setLoopResultList(detail)
setLoopResultDurationMap(loopDurationMap)
setLoopResultVariableMap(loopVariableMap)
}, [setShowLoopingDetailTrue, setLoopResultList, setLoopResultDurationMap])
const [agentOrToolLogItemStack, setAgentOrToolLogItemStack] = useState<AgentLogItemWithChildren[]>([])
@@ -101,6 +104,8 @@ export const useLogs = () => {
setLoopResultList,
loopResultDurationMap,
setLoopResultDurationMap,
loopResultVariableMap,
setLoopResultVariableMap,
handleShowLoopResultList,
agentOrToolLogItemStack,

View File

@@ -3,13 +3,14 @@ import { RiArrowRightSLine } from '@remixicon/react'
import Button from '@/app/components/base/button'
import type {
LoopDurationMap,
LoopVariableMap,
NodeTracing,
} from '@/types/workflow'
import { Loop } from '@/app/components/base/icons/src/vender/workflow'
type LoopLogTriggerProps = {
nodeInfo: NodeTracing
onShowLoopResultList: (loopResultList: NodeTracing[][], loopResultDurationMap: LoopDurationMap) => void
onShowLoopResultList: (loopResultList: NodeTracing[][], loopResultDurationMap: LoopDurationMap, loopVariableMap: LoopVariableMap) => void
}
const LoopLogTrigger = ({
nodeInfo,
@@ -35,7 +36,11 @@ const LoopLogTrigger = ({
const handleOnShowLoopDetail = (e: React.MouseEvent<HTMLButtonElement>) => {
e.stopPropagation()
e.nativeEvent.stopImmediatePropagation()
onShowLoopResultList(nodeInfo.details || [], nodeInfo?.loopDurationMap || nodeInfo.execution_metadata?.loop_duration_map || {})
onShowLoopResultList(
nodeInfo.details || [],
nodeInfo?.loopDurationMap || nodeInfo.execution_metadata?.loop_duration_map || {},
nodeInfo.execution_metadata?.loop_variable_map || {},
)
}
return (
<Button

View File

@@ -12,19 +12,23 @@ import { NodeRunningStatus } from '@/app/components/workflow/types'
import TracingPanel from '@/app/components/workflow/run/tracing-panel'
import { Loop } from '@/app/components/base/icons/src/vender/workflow'
import cn from '@/utils/classnames'
import type { LoopDurationMap, NodeTracing } from '@/types/workflow'
import type { LoopDurationMap, LoopVariableMap, NodeTracing } from '@/types/workflow'
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
import { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
const i18nPrefix = 'workflow.singleRun'
type Props = {
list: NodeTracing[][]
onBack: () => void
loopDurationMap?: LoopDurationMap
loopVariableMap?: LoopVariableMap
}
const LoopResultPanel: FC<Props> = ({
list,
onBack,
loopDurationMap,
loopVariableMap,
}) => {
const { t } = useTranslation()
const [expandedLoops, setExpandedLoops] = useState<Record<number, boolean>>({})
@@ -114,6 +118,20 @@ const LoopResultPanel: FC<Props> = ({
'overflow-hidden transition-all duration-200',
expandedLoops[index] ? 'max-h-[1000px] opacity-100' : 'max-h-0 opacity-0',
)}>
{
loopVariableMap?.[index] && (
<div className='p-2 pb-0'>
<CodeEditor
readOnly
title={<div>{t('workflow.nodes.loop.loopVariables').toLocaleUpperCase()}</div>}
language={CodeLanguage.json}
height={112}
value={loopVariableMap[index]}
isJSONStringifyBeauty
/>
</div>
)
}
<TracingPanel
list={loop}
className='bg-background-section-burn'

View File

@@ -1,7 +1,7 @@
'use client'
import { useTranslation } from 'react-i18next'
import type { FC } from 'react'
import { useCallback, useEffect, useState } from 'react'
import { useCallback, useEffect, useMemo, useState } from 'react'
import {
RiAlertFill,
RiArrowRightSLine,
@@ -23,6 +23,7 @@ import type {
AgentLogItemWithChildren,
IterationDurationMap,
LoopDurationMap,
LoopVariableMap,
NodeTracing,
} from '@/types/workflow'
import ErrorHandleTip from '@/app/components/workflow/nodes/_base/components/error-handle/error-handle-tip'
@@ -35,7 +36,7 @@ type Props = {
hideInfo?: boolean
hideProcessDetail?: boolean
onShowIterationDetail?: (detail: NodeTracing[][], iterDurationMap: IterationDurationMap) => void
onShowLoopDetail?: (detail: NodeTracing[][], loopDurationMap: LoopDurationMap) => void
onShowLoopDetail?: (detail: NodeTracing[][], loopDurationMap: LoopDurationMap, loopVariableMap: LoopVariableMap) => void
onShowRetryDetail?: (detail: NodeTracing[]) => void
onShowAgentOrToolLog?: (detail?: AgentLogItemWithChildren) => void
notShowIterationNav?: boolean
@@ -90,6 +91,20 @@ const NodePanel: FC<Props> = ({
const isAgentNode = nodeInfo.node_type === BlockEnum.Agent && !!nodeInfo.agentLog?.length
const isToolNode = nodeInfo.node_type === BlockEnum.Tool && !!nodeInfo.agentLog?.length
const inputsTitle = useMemo(() => {
let text = t('workflow.common.input')
if (nodeInfo.node_type === BlockEnum.Loop)
text = t('workflow.nodes.loop.initialLoopVariables')
return text.toLocaleUpperCase()
}, [nodeInfo.node_type, t])
const processDataTitle = t('workflow.common.processData').toLocaleUpperCase()
const outputTitle = useMemo(() => {
let text = t('workflow.common.output')
if (nodeInfo.node_type === BlockEnum.Loop)
text = t('workflow.nodes.loop.finalLoopVariables')
return text.toLocaleUpperCase()
}, [nodeInfo.node_type, t])
return (
<div className={cn('px-2 py-1', className)}>
<div className='group rounded-[10px] border border-components-panel-border bg-background-default shadow-xs transition-all hover:shadow-md'>
@@ -199,7 +214,7 @@ const NodePanel: FC<Props> = ({
<div className={cn('mb-1')}>
<CodeEditor
readOnly
title={<div>{t('workflow.common.input').toLocaleUpperCase()}</div>}
title={<div>{inputsTitle}</div>}
language={CodeLanguage.json}
value={nodeInfo.inputs}
isJSONStringifyBeauty
@@ -210,7 +225,7 @@ const NodePanel: FC<Props> = ({
<div className={cn('mb-1')}>
<CodeEditor
readOnly
title={<div>{t('workflow.common.processData').toLocaleUpperCase()}</div>}
title={<div>{processDataTitle}</div>}
language={CodeLanguage.json}
value={nodeInfo.process_data}
isJSONStringifyBeauty
@@ -221,7 +236,7 @@ const NodePanel: FC<Props> = ({
<div>
<CodeEditor
readOnly
title={<div>{t('workflow.common.output').toLocaleUpperCase()}</div>}
title={<div>{outputTitle}</div>}
language={CodeLanguage.json}
value={nodeInfo.outputs}
isJSONStringifyBeauty

View File

@@ -6,6 +6,7 @@ import type {
AgentLogItemWithChildren,
IterationDurationMap,
LoopDurationMap,
LoopVariableMap,
NodeTracing,
} from '@/types/workflow'
@@ -23,6 +24,7 @@ export type SpecialResultPanelProps = {
setShowLoopingDetailFalse?: () => void
loopResultList?: NodeTracing[][]
loopResultDurationMap?: LoopDurationMap
loopResultVariableMap?: LoopVariableMap
agentOrToolLogItemStack?: AgentLogItemWithChildren[]
agentOrToolLogListMap?: Record<string, AgentLogItemWithChildren[]>
@@ -42,6 +44,7 @@ const SpecialResultPanel = ({
setShowLoopingDetailFalse,
loopResultList,
loopResultDurationMap,
loopResultVariableMap,
agentOrToolLogItemStack,
agentOrToolLogListMap,
@@ -75,6 +78,7 @@ const SpecialResultPanel = ({
list={loopResultList}
onBack={setShowLoopingDetailFalse}
loopDurationMap={loopResultDurationMap}
loopVariableMap={loopResultVariableMap}
/>
)
}

View File

@@ -86,6 +86,7 @@ const TracingPanel: FC<TracingPanelProps> = ({
setShowLoopingDetailFalse,
loopResultList,
loopResultDurationMap,
loopResultVariableMap,
handleShowLoopResultList,
agentOrToolLogItemStack,
@@ -172,6 +173,7 @@ const TracingPanel: FC<TracingPanelProps> = ({
setShowLoopingDetailFalse={setShowLoopingDetailFalse}
loopResultList={loopResultList}
loopResultDurationMap={loopResultDurationMap}
loopResultVariableMap={loopResultVariableMap}
agentOrToolLogItemStack={agentOrToolLogItemStack}
agentOrToolLogListMap={agentOrToolLogListMap}