refact workflow run log

This commit is contained in:
zxhlyh 2024-12-26 15:44:40 +08:00
parent 1429b30e84
commit 7e94056507
10 changed files with 195 additions and 80 deletions

View File

@ -0,0 +1,43 @@
import {
RiAlertFill,
RiCheckboxCircleFill,
RiErrorWarningLine,
RiLoader2Line,
} from '@remixicon/react'
import cn from '@/utils/classnames'
type NodeStatusIconProps = {
status: string
className?: string
}
const NodeStatusIcon = ({
status,
className,
}: NodeStatusIconProps) => {
return (
<>
{
status === 'succeeded' && (
<RiCheckboxCircleFill className={cn('shrink-0 w-4 h-4 text-text-success', className)} />
)
}
{
status === 'failed' && (
<RiErrorWarningLine className={cn('shrink-0 w-4 h-4 text-text-warning', className)} />
)
}
{
(status === 'stopped' || status === 'exception') && (
<RiAlertFill className={cn('shrink-0 w-4 h-4 text-text-warning-secondary', className)} />
)
}
{
status === 'running' && (
<RiLoader2Line className={cn('shrink-0 w-4 h-4 text-text-accent animate-spin', className)} />
)
}
</>
)
}
export default NodeStatusIcon

View File

@ -0,0 +1,84 @@
import { useState } from 'react'
import {
RiArrowRightSLine,
RiListView,
} from '@remixicon/react'
import cn from '@/utils/classnames'
import Button from '@/app/components/base/button'
import type { AgentLogItemWithChildren } from '@/types/workflow'
import NodeStatusIcon from '@/app/components/workflow/nodes/_base/components/node-status-icon'
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
import { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
type AgentLogItemProps = {
item: AgentLogItemWithChildren
}
const AgentLogItem = ({
item,
}: AgentLogItemProps) => {
const {
label,
status,
children,
data,
} = item
const [expanded, setExpanded] = useState(false)
return (
<div className='border-[0.5px] border-components-panel-border rounded-[10px]'>
<div
className={cn(
'flex items-center pl-1.5 pt-2 pr-3 pb-2',
expanded && 'pb-1',
)}
onClick={() => setExpanded(!expanded)}
>
{
expanded
? <RiArrowRightSLine className='shrink-0 w-4 h-4 rotate-90' />
: <RiArrowRightSLine className='shrink-0 w-4 h-4' />
}
<div className='shrink-0 mr-1.5 w-5 h-5'></div>
<div className='grow system-sm-semibold-uppercase text-text-secondary truncate'>{label}</div>
<div className='shrink-0 mr-2 system-xs-regular text-text-tertiary'>0.02s</div>
<NodeStatusIcon status={status} />
</div>
{
expanded && (
<div className='p-1 pt-0'>
{
!!children.length && (
<Button
className='flex items-center justify-between mb-1 w-full'
variant='tertiary'
onClick={() => {}}
>
<div className='flex items-center'>
<RiListView className='mr-1 w-4 h-4 text-components-button-tertiary-text shrink-0' />
{`${children.length} Action Logs`}
</div>
<div className='flex'>
<RiArrowRightSLine className='w-4 h-4 text-components-button-tertiary-text shrink-0' />
</div>
</Button>
)
}
{
data && (
<CodeEditor
readOnly
title={<div>{'data'.toLocaleUpperCase()}</div>}
language={CodeLanguage.json}
value={data}
isJSONStringifyBeauty
/>
)
}
</div>
)
}
</div>
)
}
export default AgentLogItem

View File

@ -1,11 +1,19 @@
import { RiArrowRightLine } from '@remixicon/react'
import type {
AgentLogItemWithChildren,
NodeTracing,
} from '@/types/workflow'
type AgentLogTriggerProps = {
onDetail?: () => void
nodeInfo: NodeTracing
onShowAgentResultList: (agentLogs: AgentLogItemWithChildren[]) => void
}
const AgentLogTrigger = ({
onDetail,
nodeInfo,
onShowAgentResultList,
}: AgentLogTriggerProps) => {
const { agentLog } = nodeInfo
return (
<div className='bg-components-button-tertiary-bg rounded-[10px]'>
<div className='flex items-center px-3 pt-2 system-2xs-medium-uppercase text-text-tertiary'>
@ -16,7 +24,7 @@ const AgentLogTrigger = ({
<div className='grow mx-0.5 px-1 system-xs-medium text-text-secondary'></div>
<div
className='shrink-0 flex items-center px-[1px] system-xs-regular-uppercase text-text-tertiary cursor-pointer'
onClick={onDetail}
onClick={() => onShowAgentResultList(agentLog || [])}
>
Detail
<RiArrowRightLine className='ml-0.5 w-3.5 h-3.5' />

View File

@ -1,12 +1,14 @@
import Button from '@/app/components/base/button'
import { RiArrowLeftLine } from '@remixicon/react'
import TracingPanel from '../tracing-panel'
import AgentLogItem from './agent-log-item'
import type { AgentLogItemWithChildren } from '@/types/workflow'
type AgentResultPanelProps = {
onBack: () => void
list: AgentLogItemWithChildren[]
setAgentResultList: (list: AgentLogItemWithChildren[]) => void
}
const AgentResultPanel = ({
onBack,
list,
}: AgentResultPanelProps) => {
return (
<div className='overflow-y-auto'>
@ -15,7 +17,7 @@ const AgentResultPanel = ({
className='shrink-0 px-[5px]'
size='small'
variant='ghost-accent'
onClick={onBack}
onClick={() => {}}
>
<RiArrowLeftLine className='mr-1 w-3.5 h-3.5' />
Back
@ -28,14 +30,23 @@ const AgentResultPanel = ({
className='px-[5px]'
size='small'
variant='ghost-accent'
onClick={onBack}
onClick={() => {}}
>
close
</Button>
</div>
<TracingPanel
list={[]}
/>
{
<div className='p-2'>
{
list.map(item => (
<AgentLogItem
key={item.id}
item={item}
/>
))
}
</div>
}
</div>
)
}

View File

@ -1,3 +1,2 @@
export { default as AgentLogTrigger } from './agent-log-trigger'
export { default as AgentResultPanel } from './agent-result-panel'
export { default as AgentToolCallResultPanel } from './tool-call-result-panel'

View File

@ -1,45 +0,0 @@
import Button from '@/app/components/base/button'
import { RiArrowLeftLine } from '@remixicon/react'
import TracingPanel from '../tracing-panel'
type ToolCallResultPanelProps = {
onBack: () => void
onClose: () => void
}
const ToolCallResultPanel = ({
onBack,
onClose,
}: ToolCallResultPanelProps) => {
return (
<div className='overflow-y-auto'>
<div className='flex items-center p-1 pr-3 h-8'>
<Button
className='shrink-0 px-[5px]'
size='small'
variant='ghost-accent'
onClick={onBack}
>
<RiArrowLeftLine className='mr-1 w-3.5 h-3.5' />
Back
</Button>
<div className='shrink-0 mx-0.5 system-xs-regular text-divider-deep'>/</div>
<div className='grow px-[5px] system-xs-medium-uppercase'>
10 Logs
</div>
<Button
className='px-[5px]'
size='small'
variant='ghost-accent'
onClick={onClose}
>
close
</Button>
</div>
<TracingPanel
list={[]}
/>
</div>
)
}
export default ToolCallResultPanel

View File

@ -3,7 +3,11 @@ import {
useState,
} from 'react'
import { useBoolean } from 'ahooks'
import type { IterationDurationMap, NodeTracing } from '@/types/workflow'
import type {
AgentLogItemWithChildren,
IterationDurationMap,
NodeTracing,
} from '@/types/workflow'
export const useLogs = () => {
const [showRetryDetail, {
@ -28,13 +32,10 @@ export const useLogs = () => {
setIterationResultDurationMap(iterDurationMap)
}, [setShowIteratingDetailTrue, setIterationResultList, setIterationResultDurationMap])
const [showAgentDetail, {
setTrue: setShowAgentDetailTrue,
setFalse: setShowAgentDetailFalse,
}] = useBoolean(false)
const [agentResultList, setAgentResultList] = useState<AgentLogItemWithChildren[]>([])
return {
showSpecialResultPanel: showRetryDetail || showIteratingDetail,
showSpecialResultPanel: showRetryDetail || showIteratingDetail || !!agentResultList.length,
showRetryDetail,
setShowRetryDetailTrue,
setShowRetryDetailFalse,
@ -51,8 +52,7 @@ export const useLogs = () => {
setIterationResultDurationMap,
handleShowIterationResultList,
showAgentDetail,
setShowAgentDetailTrue,
setShowAgentDetailFalse,
agentResultList,
setAgentResultList,
}
}

View File

@ -18,7 +18,11 @@ import cn from '@/utils/classnames'
import StatusContainer from '@/app/components/workflow/run/status-container'
import CodeEditor from '@/app/components/workflow/nodes/_base/components/editor/code-editor'
import { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
import type { IterationDurationMap, NodeTracing } from '@/types/workflow'
import type {
AgentLogItemWithChildren,
IterationDurationMap,
NodeTracing,
} from '@/types/workflow'
import ErrorHandleTip from '@/app/components/workflow/nodes/_base/components/error-handle/error-handle-tip'
import { hasRetryNode } from '@/app/components/workflow/utils'
@ -30,6 +34,7 @@ type Props = {
hideProcessDetail?: boolean
onShowIterationDetail?: (detail: NodeTracing[][], iterDurationMap: IterationDurationMap) => void
onShowRetryDetail?: (detail: NodeTracing[]) => void
onShowAgentResultList?: (detail: AgentLogItemWithChildren[]) => void
notShowIterationNav?: boolean
justShowIterationNavArrow?: boolean
justShowRetryNavArrow?: boolean
@ -43,6 +48,7 @@ const NodePanel: FC<Props> = ({
hideProcessDetail,
onShowIterationDetail,
onShowRetryDetail,
onShowAgentResultList,
notShowIterationNav,
justShowIterationNavArrow,
}) => {
@ -142,8 +148,11 @@ const NodePanel: FC<Props> = ({
/>
)}
{
isAgentNode && (
<AgentLogTrigger />
isAgentNode && onShowAgentResultList && (
<AgentLogTrigger
nodeInfo={nodeInfo}
onShowAgentResultList={onShowAgentResultList}
/>
)
}
<div className={cn('mb-1', hideInfo && '!px-2 !py-0.5')}>

View File

@ -1,7 +1,11 @@
import { RetryResultPanel } from './retry-log'
import { IterationResultPanel } from './iteration-log'
import { AgentResultPanel } from './agent-log'
import type { IterationDurationMap, NodeTracing } from '@/types/workflow'
import type {
AgentLogItemWithChildren,
IterationDurationMap,
NodeTracing,
} from '@/types/workflow'
type SpecialResultPanelProps = {
showRetryDetail: boolean
@ -13,8 +17,8 @@ type SpecialResultPanelProps = {
iterationResultList: NodeTracing[][]
iterationResultDurationMap: IterationDurationMap
showAgentDetail: boolean
setShowAgentDetailFalse: () => void
agentResultList: AgentLogItemWithChildren[]
setAgentResultList: (list: AgentLogItemWithChildren[]) => void
}
const SpecialResultPanel = ({
showRetryDetail,
@ -26,8 +30,8 @@ const SpecialResultPanel = ({
iterationResultList,
iterationResultDurationMap,
showAgentDetail,
setShowAgentDetailFalse,
agentResultList,
setAgentResultList,
}: SpecialResultPanelProps) => {
return (
<>
@ -49,9 +53,10 @@ const SpecialResultPanel = ({
)
}
{
showAgentDetail && (
!!agentResultList.length && (
<AgentResultPanel
onBack={setShowAgentDetailFalse}
list={agentResultList}
setAgentResultList={setAgentResultList}
/>
)
}

View File

@ -215,8 +215,8 @@ const TracingPanel: FC<TracingPanelProps> = ({
iterationResultDurationMap,
handleShowIterationResultList,
showAgentDetail,
setShowAgentDetailFalse,
agentResultList,
setAgentResultList,
} = useLogs()
const renderNode = (node: TracingNodeProps) => {
@ -270,6 +270,7 @@ const TracingPanel: FC<TracingPanelProps> = ({
nodeInfo={node.data!}
onShowIterationDetail={handleShowIterationResultList}
onShowRetryDetail={handleShowRetryResultList}
onShowAgentResultList={setAgentResultList}
justShowIterationNavArrow={true}
justShowRetryNavArrow={true}
hideInfo={hideNodeInfo}
@ -292,8 +293,8 @@ const TracingPanel: FC<TracingPanelProps> = ({
iterationResultList={iterationResultList}
iterationResultDurationMap={iterationResultDurationMap}
showAgentDetail={showAgentDetail}
setShowAgentDetailFalse={setShowAgentDetailFalse}
agentResultList={agentResultList}
setAgentResultList={setAgentResultList}
/>
)
}