mirror of https://github.com/langgenius/dify.git
Merge branch 'feat/plugins' of https://github.com/langgenius/dify into feat/plugins
This commit is contained in:
commit
c476f06388
|
|
@ -3,7 +3,6 @@ import { useMemo, useState } from 'react'
|
|||
import type { Strategy } from './agent-strategy'
|
||||
import classNames from '@/utils/classnames'
|
||||
import { RiArrowDownSLine, RiArrowRightUpLine, RiErrorWarningFill } from '@remixicon/react'
|
||||
import { useAllBuiltInTools } from '@/service/use-tools'
|
||||
import Tooltip from '@/app/components/base/tooltip'
|
||||
import Link from 'next/link'
|
||||
import { InstallPluginButton } from './install-plugin-button'
|
||||
|
|
@ -12,6 +11,10 @@ import SearchInput from '@/app/components/base/search-input'
|
|||
import { MARKETPLACE_URL_PREFIX } from '@/config'
|
||||
import Tools from '../../../block-selector/tools'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { useStrategyProviders } from '@/service/use-strategy'
|
||||
import type { StrategyPluginDetail } from '@/app/components/plugins/types'
|
||||
import type { ToolWithProvider } from '../../../types'
|
||||
import { CollectionType } from '@/app/components/tools/types'
|
||||
|
||||
const ExternalNotInstallWarn = () => {
|
||||
const { t } = useTranslation()
|
||||
|
|
@ -31,6 +34,36 @@ const ExternalNotInstallWarn = () => {
|
|||
</Tooltip>
|
||||
}
|
||||
|
||||
function formatStrategy(input: StrategyPluginDetail[]): ToolWithProvider[] {
|
||||
return input.map((item) => {
|
||||
const res: ToolWithProvider = {
|
||||
id: item.provider,
|
||||
// TODO: replace this
|
||||
author: item.declaration.identity.author,
|
||||
name: item.declaration.identity.name,
|
||||
description: item.declaration.identity.description as any,
|
||||
plugin_id: item.plugin_id,
|
||||
icon: item.declaration.identity.icon,
|
||||
label: item.declaration.identity.label as any,
|
||||
type: CollectionType.all,
|
||||
tools: item.declaration.strategies.map(strategy => ({
|
||||
name: strategy.identity.name,
|
||||
author: strategy.identity.author,
|
||||
label: strategy.identity.label as any,
|
||||
description: strategy.description,
|
||||
parameters: strategy.parameters as any,
|
||||
output_schema: strategy.output_schema,
|
||||
labels: [],
|
||||
})),
|
||||
team_credentials: {},
|
||||
is_team_authorization: true,
|
||||
allow_delete: false,
|
||||
labels: [],
|
||||
}
|
||||
return res
|
||||
})
|
||||
}
|
||||
|
||||
export type AgentStrategySelectorProps = {
|
||||
value?: Strategy,
|
||||
onChange: (value?: Strategy) => void,
|
||||
|
|
@ -39,13 +72,15 @@ export type AgentStrategySelectorProps = {
|
|||
export const AgentStrategySelector = (props: AgentStrategySelectorProps) => {
|
||||
const { value, onChange } = props
|
||||
const [open, setOpen] = useState(false)
|
||||
const list = useAllBuiltInTools()
|
||||
const [viewType, setViewType] = useState<ViewType>(ViewType.flat)
|
||||
const [query, setQuery] = useState('')
|
||||
const stra = useStrategyProviders()
|
||||
const list = stra.data ? formatStrategy(stra.data) : undefined
|
||||
console.log('list', list, 'stra', stra)
|
||||
const filteredTools = useMemo(() => {
|
||||
if (!list.data) return []
|
||||
return list.data.filter(tool => tool.name.toLowerCase().includes(query.toLowerCase()))
|
||||
}, [query, list.data])
|
||||
if (!list) return []
|
||||
return list.filter(tool => tool.name.toLowerCase().includes(query.toLowerCase()))
|
||||
}, [query, list])
|
||||
// TODO: should be replaced by real data
|
||||
const isExternalInstalled = true
|
||||
const { t } = useTranslation()
|
||||
|
|
@ -53,9 +88,9 @@ export const AgentStrategySelector = (props: AgentStrategySelectorProps) => {
|
|||
<PortalToFollowElemTrigger className='w-full'>
|
||||
<div className='py-2 pl-3 pr-2 flex items-center rounded-lg bg-components-input-bg-normal w-full hover:bg-state-base-hover-alt select-none' onClick={() => setOpen(o => !o)}>
|
||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||
{list.data && value && <img
|
||||
src={list.data.find(
|
||||
coll => coll,
|
||||
{list && value && <img
|
||||
src={list.find(
|
||||
coll => coll.tools?.find(tool => tool.name === value.agent_strategy_name),
|
||||
)?.icon as string}
|
||||
width={20}
|
||||
height={20}
|
||||
|
|
@ -65,7 +100,7 @@ export const AgentStrategySelector = (props: AgentStrategySelectorProps) => {
|
|||
<p
|
||||
className={classNames(value ? 'text-components-input-text-filled' : 'text-components-input-text-placeholder', 'text-xs px-1')}
|
||||
>
|
||||
{value?.agent_strategy_name || t('workflow.nodes.agent.strategy.selectTip')}
|
||||
{value?.agent_strategy_label || t('workflow.nodes.agent.strategy.selectTip')}
|
||||
</p>
|
||||
{value && <div className='ml-auto flex items-center gap-1'>
|
||||
<InstallPluginButton onClick={e => e.stopPropagation()} size={'small'} />
|
||||
|
|
@ -85,10 +120,12 @@ export const AgentStrategySelector = (props: AgentStrategySelectorProps) => {
|
|||
viewType={viewType}
|
||||
onSelect={(_, tool) => {
|
||||
onChange({
|
||||
agent_strategy_name: tool!.title,
|
||||
agent_strategy_name: tool!.tool_name,
|
||||
agent_strategy_provider_name: tool!.provider_name,
|
||||
agent_parameters: tool!.params,
|
||||
agent_strategy_label: tool!.tool_label,
|
||||
})
|
||||
console.log(tool, 'tool')
|
||||
setOpen(false)
|
||||
}}
|
||||
hasSearchText={false}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import { Agent } from '@/app/components/base/icons/src/vender/workflow'
|
|||
export type Strategy = {
|
||||
agent_strategy_provider_name: string
|
||||
agent_strategy_name: string
|
||||
agent_strategy_label?: string
|
||||
agent_strategy_label: string
|
||||
agent_parameters?: ToolVarInputs
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import Toast from '@/app/components/base/toast'
|
|||
import { TransferMethod } from '@/types/app'
|
||||
import { getProcessedFiles } from '@/app/components/base/file-uploader/utils'
|
||||
import type { NodeTracing } from '@/types/workflow'
|
||||
import RetryResultPanel from '@/app/components/workflow/run/retry-result-panel'
|
||||
import { RetryResultPanel } from '@/app/components/workflow/run/retry-log'
|
||||
import type { BlockEnum } from '@/app/components/workflow/types'
|
||||
import type { Emoji } from '@/app/components/tools/types'
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ const AgentNode: FC<NodeProps<AgentNodeType>> = (props) => {
|
|||
label={t('workflow.nodes.agent.strategy.shortLabel')}
|
||||
status='error'
|
||||
tooltip={t('workflow.nodes.agent.strategyNotInstallTooltip', {
|
||||
strategy: inputs.agent_strategy_name,
|
||||
strategy: inputs.agent_strategy_label,
|
||||
})}
|
||||
>
|
||||
{inputs.agent_strategy_name}
|
||||
{inputs.agent_strategy_label}
|
||||
</SettingItem>
|
||||
: <SettingItem label={t('workflow.nodes.agent.strategyNotSet')} />}
|
||||
<Group
|
||||
|
|
|
|||
|
|
@ -7,48 +7,9 @@ import Slider from '@/app/components/base/slider'
|
|||
import { AgentStrategy } from '../_base/components/agent-strategy'
|
||||
import useConfig from './use-config'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { type CredentialFormSchema, FormTypeEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
|
||||
|
||||
// @ts-expect-error fuck
|
||||
const mockSchema = [
|
||||
{
|
||||
name: 'format',
|
||||
label: {
|
||||
en_US: 'Format',
|
||||
zh_Hans: '格式',
|
||||
pt_BR: 'Format',
|
||||
ja_JP: 'Format',
|
||||
},
|
||||
placeholder: undefined,
|
||||
scope: undefined,
|
||||
required: false,
|
||||
default: '%Y-%m-%d %H:%M:%S',
|
||||
options: [],
|
||||
type: 'text-input',
|
||||
form: 'form',
|
||||
llm_description: null,
|
||||
variable: 'format',
|
||||
_type: 'string',
|
||||
show_on: [],
|
||||
tooltip: {
|
||||
en_US: 'Time format in strftime standard.',
|
||||
zh_Hans: 'strftime 标准的时间格式。',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'model',
|
||||
type: FormTypeEnum.modelSelector,
|
||||
label: {
|
||||
en_US: 'Model',
|
||||
zh_Hans: '模型',
|
||||
},
|
||||
variable: 'model',
|
||||
scope: 'all',
|
||||
},
|
||||
] as Array<CredentialFormSchema & { name: string }>
|
||||
|
||||
const AgentPanel: FC<NodePanelProps<AgentNodeType>> = (props) => {
|
||||
const { inputs, setInputs } = useConfig(props.id, props.data)
|
||||
const { inputs, setInputs, currentStrategy } = useConfig(props.id, props.data)
|
||||
const { t } = useTranslation()
|
||||
const [iter, setIter] = [inputs.max_iterations, (value: number) => {
|
||||
setInputs({
|
||||
|
|
@ -63,6 +24,7 @@ const AgentPanel: FC<NodePanelProps<AgentNodeType>> = (props) => {
|
|||
agent_strategy_provider_name: inputs.agent_strategy_provider_name!,
|
||||
agent_strategy_name: inputs.agent_strategy_name!,
|
||||
agent_parameters: inputs.agent_parameters,
|
||||
agent_strategy_label: inputs.agent_strategy_label!,
|
||||
} : undefined}
|
||||
onStrategyChange={(strategy) => {
|
||||
setInputs({
|
||||
|
|
@ -70,9 +32,10 @@ const AgentPanel: FC<NodePanelProps<AgentNodeType>> = (props) => {
|
|||
agent_strategy_provider_name: strategy?.agent_strategy_provider_name,
|
||||
agent_strategy_name: strategy?.agent_strategy_name,
|
||||
agent_parameters: strategy?.agent_parameters,
|
||||
agent_strategy_label: strategy?.agent_strategy_label,
|
||||
})
|
||||
}}
|
||||
formSchema={mockSchema as any}
|
||||
formSchema={currentStrategy?.parameters as any || []}
|
||||
formValue={inputs.agent_parameters || {}}
|
||||
onFormValueChange={value => setInputs({
|
||||
...inputs,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { useStrategyProviderDetail } from '@/service/use-strategy'
|
||||
import useNodeCrud from '../_base/hooks/use-node-crud'
|
||||
import useVarList from '../_base/hooks/use-var-list'
|
||||
import type { AgentNodeType } from './types'
|
||||
|
|
@ -13,13 +14,20 @@ const useConfig = (id: string, payload: AgentNodeType) => {
|
|||
inputs,
|
||||
setInputs,
|
||||
})
|
||||
|
||||
const strategies = useStrategyProviderDetail(
|
||||
inputs.agent_strategy_provider_name || '',
|
||||
)
|
||||
const currentStrategy = strategies.data?.declaration.strategies.find(
|
||||
str => str.identity.name === inputs.agent_strategy_name,
|
||||
)
|
||||
console.log('currentStrategy', currentStrategy, 'strategies', strategies, 'inputs', inputs)
|
||||
return {
|
||||
readOnly,
|
||||
inputs,
|
||||
setInputs,
|
||||
handleVarListChange,
|
||||
handleAddVariable,
|
||||
currentStrategy,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {
|
|||
import VarReferencePicker from '../_base/components/variable/var-reference-picker'
|
||||
import Split from '../_base/components/split'
|
||||
import ResultPanel from '../../run/result-panel'
|
||||
import IterationResultPanel from '../../run/iteration-result-panel'
|
||||
import { IterationResultPanel } from '../../run/iteration-log'
|
||||
import { MAX_ITERATION_PARALLEL_NUM, MIN_ITERATION_PARALLEL_NUM } from '../../constants'
|
||||
import type { IterationNodeType } from './types'
|
||||
import useConfig from './use-config'
|
||||
|
|
@ -123,7 +123,7 @@ const Panel: FC<NodePanelProps<IterationNodeType>> = ({
|
|||
onChange={changeParallelNums}
|
||||
max={MAX_ITERATION_PARALLEL_NUM}
|
||||
min={MIN_ITERATION_PARALLEL_NUM}
|
||||
className=' flex-shrink-0 flex-1 mt-4'
|
||||
className=' shrink-0 flex-1 mt-4'
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ import {
|
|||
} from '../types'
|
||||
import { SimpleBtn } from '../../app/text-generate/item'
|
||||
import Toast from '../../base/toast'
|
||||
import IterationResultPanel from '../run/iteration-result-panel'
|
||||
import RetryResultPanel from '../run/retry-result-panel'
|
||||
import { IterationResultPanel } from '../run/iteration-log'
|
||||
import { RetryResultPanel } from '../run/retry-log'
|
||||
import InputsPanel from './inputs-panel'
|
||||
import cn from '@/utils/classnames'
|
||||
import Loading from '@/app/components/base/loading'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
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'
|
||||
|
|
@ -28,14 +28,20 @@ export const useLogs = () => {
|
|||
setIterationResultDurationMap(iterDurationMap)
|
||||
}, [setShowIteratingDetailTrue, setIterationResultList, setIterationResultDurationMap])
|
||||
|
||||
const [showAgentDetail, {
|
||||
setTrue: setShowAgentDetailTrue,
|
||||
setFalse: setShowAgentDetailFalse,
|
||||
}] = useBoolean(false)
|
||||
|
||||
return {
|
||||
showSpecialResultPanel: !showRetryDetail && !showIteratingDetail,
|
||||
showSpecialResultPanel: showRetryDetail || showIteratingDetail,
|
||||
showRetryDetail,
|
||||
setShowRetryDetailTrue,
|
||||
setShowRetryDetailFalse,
|
||||
retryResultList,
|
||||
setRetryResultList,
|
||||
handleShowRetryResultList,
|
||||
|
||||
showIteratingDetail,
|
||||
setShowIteratingDetailTrue,
|
||||
setShowIteratingDetailFalse,
|
||||
|
|
@ -44,5 +50,9 @@ export const useLogs = () => {
|
|||
iterationResultDurationMap,
|
||||
setIterationResultDurationMap,
|
||||
handleShowIterationResultList,
|
||||
|
||||
showAgentDetail,
|
||||
setShowAgentDetailTrue,
|
||||
setShowAgentDetailFalse,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,16 +106,21 @@ const RunPanel: FC<RunProps> = ({ hideResult, activeTab = 'RESULT', runID, getRe
|
|||
}, [loading])
|
||||
|
||||
const {
|
||||
showSpecialResultPanel,
|
||||
|
||||
showRetryDetail,
|
||||
setShowRetryDetailFalse,
|
||||
retryResultList,
|
||||
handleShowRetryResultList,
|
||||
|
||||
showIteratingDetail,
|
||||
setShowIteratingDetailFalse,
|
||||
iterationResultList,
|
||||
iterationResultDurationMap,
|
||||
handleShowIterationResultList,
|
||||
showSpecialResultPanel,
|
||||
|
||||
showAgentDetail,
|
||||
setShowAgentDetailFalse,
|
||||
} = useLogs()
|
||||
|
||||
return (
|
||||
|
|
@ -193,6 +198,9 @@ const RunPanel: FC<RunProps> = ({ hideResult, activeTab = 'RESULT', runID, getRe
|
|||
setShowIteratingDetailFalse={setShowIteratingDetailFalse}
|
||||
iterationResultList={iterationResultList}
|
||||
iterationResultDurationMap={iterationResultDurationMap}
|
||||
|
||||
showAgentDetail={showAgentDetail}
|
||||
setShowAgentDetailFalse={setShowAgentDetailFalse}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
export { default as IterationLogTrigger } from './iteration-log-trigger'
|
||||
export { default as IterationResultPanel } from './iteration-result-panel'
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
import { useTranslation } from 'react-i18next'
|
||||
import { RiArrowRightSLine } from '@remixicon/react'
|
||||
import Button from '@/app/components/base/button'
|
||||
import type {
|
||||
IterationDurationMap,
|
||||
NodeTracing,
|
||||
} from '@/types/workflow'
|
||||
import { Iteration } from '@/app/components/base/icons/src/vender/workflow'
|
||||
import Split from '@/app/components/workflow/nodes/_base/components/split'
|
||||
|
||||
type IterationLogTriggerProps = {
|
||||
nodeInfo: NodeTracing
|
||||
onShowIterationResultList: (iterationResultList: NodeTracing[][], iterationResultDurationMap: IterationDurationMap) => void
|
||||
justShowIterationNavArrow?: boolean
|
||||
}
|
||||
const IterationLogTrigger = ({
|
||||
nodeInfo,
|
||||
onShowIterationResultList,
|
||||
justShowIterationNavArrow,
|
||||
}: IterationLogTriggerProps) => {
|
||||
const { t } = useTranslation()
|
||||
const getErrorCount = (details: NodeTracing[][] | undefined) => {
|
||||
if (!details || details.length === 0)
|
||||
return 0
|
||||
|
||||
return details.reduce((acc, iteration) => {
|
||||
if (iteration.some(item => item.status === 'failed'))
|
||||
acc++
|
||||
return acc
|
||||
}, 0)
|
||||
}
|
||||
const getCount = (iteration_curr_length: number | undefined, iteration_length: number) => {
|
||||
if ((iteration_curr_length && iteration_curr_length < iteration_length) || !iteration_length)
|
||||
return iteration_curr_length
|
||||
|
||||
return iteration_length
|
||||
}
|
||||
const handleOnShowIterationDetail = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation()
|
||||
e.nativeEvent.stopImmediatePropagation()
|
||||
onShowIterationResultList(nodeInfo.details || [], nodeInfo?.iterDurationMap || nodeInfo.execution_metadata?.iteration_duration_map || {})
|
||||
}
|
||||
return (
|
||||
<div className='mt-2 mb-1 !px-2'>
|
||||
<Button
|
||||
className='flex items-center w-full self-stretch gap-2 px-3 py-2 bg-components-button-tertiary-bg-hover hover:bg-components-button-tertiary-bg-hover rounded-lg cursor-pointer border-none'
|
||||
onClick={handleOnShowIterationDetail}
|
||||
>
|
||||
<Iteration className='w-4 h-4 text-components-button-tertiary-text shrink-0' />
|
||||
<div className='flex-1 text-left system-sm-medium text-components-button-tertiary-text'>{t('workflow.nodes.iteration.iteration', { count: getCount(nodeInfo.details?.length, nodeInfo.metadata?.iterator_length) })}{getErrorCount(nodeInfo.details) > 0 && (
|
||||
<>
|
||||
{t('workflow.nodes.iteration.comma')}
|
||||
{t('workflow.nodes.iteration.error', { count: getErrorCount(nodeInfo.details) })}
|
||||
</>
|
||||
)}</div>
|
||||
{justShowIterationNavArrow
|
||||
? (
|
||||
<RiArrowRightSLine className='w-4 h-4 text-components-button-tertiary-text shrink-0' />
|
||||
)
|
||||
: (
|
||||
<div className='flex items-center space-x-1 text-[#155EEF]'>
|
||||
<div className='text-[13px] font-normal '>{t('workflow.common.viewDetailInTracingPanel')}</div>
|
||||
<RiArrowRightSLine className='w-4 h-4 text-components-button-tertiary-text shrink-0' />
|
||||
</div>
|
||||
)}
|
||||
</Button>
|
||||
<Split className='mt-2' />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default IterationLogTrigger
|
||||
|
|
@ -8,10 +8,10 @@ import {
|
|||
RiErrorWarningLine,
|
||||
RiLoader2Line,
|
||||
} from '@remixicon/react'
|
||||
import { ArrowNarrowLeft } from '../../base/icons/src/vender/line/arrows'
|
||||
import { NodeRunningStatus } from '../types'
|
||||
import TracingPanel from './tracing-panel'
|
||||
import RetryResultPanel from './retry-result-panel'
|
||||
import { ArrowNarrowLeft } from '@/app/components/base/icons/src/vender/line/arrows'
|
||||
import { NodeRunningStatus } from '@/app/components/workflow/types'
|
||||
import TracingPanel from '@/app/components/workflow/run/tracing-panel'
|
||||
import { RetryResultPanel } from '@/app/components/workflow/run/retry-log'
|
||||
import { Iteration } from '@/app/components/base/icons/src/vender/workflow'
|
||||
import cn from '@/utils/classnames'
|
||||
import type { IterationDurationMap, NodeTracing } from '@/types/workflow'
|
||||
|
|
@ -8,16 +8,15 @@ import {
|
|||
RiCheckboxCircleFill,
|
||||
RiErrorWarningLine,
|
||||
RiLoader2Line,
|
||||
RiRestartFill,
|
||||
} from '@remixicon/react'
|
||||
import BlockIcon from '../block-icon'
|
||||
import { BlockEnum } from '../types'
|
||||
import Split from '../nodes/_base/components/split'
|
||||
import { Iteration } from '@/app/components/base/icons/src/vender/workflow'
|
||||
import { RetryLogTrigger } from './retry-log'
|
||||
import { IterationLogTrigger } from './iteration-log'
|
||||
import { AgentLogTrigger } from './agent-log'
|
||||
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 Button from '@/app/components/base/button'
|
||||
import { CodeLanguage } from '@/app/components/workflow/nodes/code/types'
|
||||
import type { IterationDurationMap, NodeTracing } from '@/types/workflow'
|
||||
import ErrorHandleTip from '@/app/components/workflow/nodes/_base/components/error-handle/error-handle-tip'
|
||||
|
|
@ -72,38 +71,14 @@ const NodePanel: FC<Props> = ({
|
|||
return `${Number.parseFloat((tokens / 1000000).toFixed(3))}M`
|
||||
}
|
||||
|
||||
const getCount = (iteration_curr_length: number | undefined, iteration_length: number) => {
|
||||
if ((iteration_curr_length && iteration_curr_length < iteration_length) || !iteration_length)
|
||||
return iteration_curr_length
|
||||
|
||||
return iteration_length
|
||||
}
|
||||
const getErrorCount = (details: NodeTracing[][] | undefined) => {
|
||||
if (!details || details.length === 0)
|
||||
return 0
|
||||
|
||||
return details.reduce((acc, iteration) => {
|
||||
if (iteration.some(item => item.status === 'failed'))
|
||||
acc++
|
||||
return acc
|
||||
}, 0)
|
||||
}
|
||||
useEffect(() => {
|
||||
setCollapseState(!nodeInfo.expand)
|
||||
}, [nodeInfo.expand, setCollapseState])
|
||||
|
||||
const isIterationNode = nodeInfo.node_type === BlockEnum.Iteration
|
||||
const isRetryNode = hasRetryNode(nodeInfo.node_type) && nodeInfo.retryDetail
|
||||
const handleOnShowIterationDetail = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation()
|
||||
e.nativeEvent.stopImmediatePropagation()
|
||||
onShowIterationDetail?.(nodeInfo.details || [], nodeInfo?.iterDurationMap || nodeInfo.execution_metadata?.iteration_duration_map || {})
|
||||
}
|
||||
const handleOnShowRetryDetail = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation()
|
||||
e.nativeEvent.stopImmediatePropagation()
|
||||
onShowRetryDetail?.(nodeInfo.retryDetail || [])
|
||||
}
|
||||
const isAgentNode = nodeInfo.node_type === BlockEnum.Agent
|
||||
|
||||
return (
|
||||
<div className={cn('px-2 py-1', className)}>
|
||||
<div className='group transition-all bg-background-default border border-components-panel-border rounded-[10px] shadow-xs hover:shadow-md'>
|
||||
|
|
@ -153,46 +128,24 @@ const NodePanel: FC<Props> = ({
|
|||
{!collapseState && !hideProcessDetail && (
|
||||
<div className='px-1 pb-1'>
|
||||
{/* The nav to the iteration detail */}
|
||||
{isIterationNode && !notShowIterationNav && (
|
||||
<div className='mt-2 mb-1 !px-2'>
|
||||
<Button
|
||||
className='flex items-center w-full self-stretch gap-2 px-3 py-2 bg-components-button-tertiary-bg-hover hover:bg-components-button-tertiary-bg-hover rounded-lg cursor-pointer border-none'
|
||||
onClick={handleOnShowIterationDetail}
|
||||
>
|
||||
<Iteration className='w-4 h-4 text-components-button-tertiary-text shrink-0' />
|
||||
<div className='flex-1 text-left system-sm-medium text-components-button-tertiary-text'>{t('workflow.nodes.iteration.iteration', { count: getCount(nodeInfo.details?.length, nodeInfo.metadata?.iterator_length) })}{getErrorCount(nodeInfo.details) > 0 && (
|
||||
<>
|
||||
{t('workflow.nodes.iteration.comma')}
|
||||
{t('workflow.nodes.iteration.error', { count: getErrorCount(nodeInfo.details) })}
|
||||
</>
|
||||
)}</div>
|
||||
{justShowIterationNavArrow
|
||||
? (
|
||||
<RiArrowRightSLine className='w-4 h-4 text-components-button-tertiary-text shrink-0' />
|
||||
)
|
||||
: (
|
||||
<div className='flex items-center space-x-1 text-[#155EEF]'>
|
||||
<div className='text-[13px] font-normal '>{t('workflow.common.viewDetailInTracingPanel')}</div>
|
||||
<RiArrowRightSLine className='w-4 h-4 text-components-button-tertiary-text shrink-0' />
|
||||
</div>
|
||||
)}
|
||||
</Button>
|
||||
<Split className='mt-2' />
|
||||
</div>
|
||||
{isIterationNode && !notShowIterationNav && onShowIterationDetail && (
|
||||
<IterationLogTrigger
|
||||
nodeInfo={nodeInfo}
|
||||
onShowIterationResultList={onShowIterationDetail}
|
||||
justShowIterationNavArrow={justShowIterationNavArrow}
|
||||
/>
|
||||
)}
|
||||
{isRetryNode && (
|
||||
<Button
|
||||
className='flex items-center justify-between mb-1 w-full'
|
||||
variant='tertiary'
|
||||
onClick={handleOnShowRetryDetail}
|
||||
>
|
||||
<div className='flex items-center'>
|
||||
<RiRestartFill className='mr-0.5 w-4 h-4 text-components-button-tertiary-text shrink-0' />
|
||||
{t('workflow.nodes.common.retry.retries', { num: nodeInfo.retryDetail?.length })}
|
||||
</div>
|
||||
<RiArrowRightSLine className='w-4 h-4 text-components-button-tertiary-text shrink-0' />
|
||||
</Button>
|
||||
{isRetryNode && onShowRetryDetail && (
|
||||
<RetryLogTrigger
|
||||
nodeInfo={nodeInfo}
|
||||
onShowRetryResultList={onShowRetryDetail}
|
||||
/>
|
||||
)}
|
||||
{
|
||||
isAgentNode && (
|
||||
<AgentLogTrigger />
|
||||
)
|
||||
}
|
||||
<div className={cn('mb-1', hideInfo && '!px-2 !py-0.5')}>
|
||||
{(nodeInfo.status === 'stopped') && (
|
||||
<StatusContainer status='stopped'>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
export { default as RetryLogTrigger } from './retry-log-trigger'
|
||||
export { default as RetryResultPanel } from './retry-result-panel'
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
import { useTranslation } from 'react-i18next'
|
||||
import {
|
||||
RiArrowRightSLine,
|
||||
RiRestartFill,
|
||||
} from '@remixicon/react'
|
||||
import Button from '@/app/components/base/button'
|
||||
import type { NodeTracing } from '@/types/workflow'
|
||||
|
||||
type RetryLogTriggerProps = {
|
||||
nodeInfo: NodeTracing
|
||||
onShowRetryResultList: (detail: NodeTracing[]) => void
|
||||
}
|
||||
const RetryLogTrigger = ({
|
||||
nodeInfo,
|
||||
onShowRetryResultList,
|
||||
}: RetryLogTriggerProps) => {
|
||||
const { t } = useTranslation()
|
||||
const { retryDetail } = nodeInfo
|
||||
|
||||
const handleShowRetryResultList = (e: React.MouseEvent<HTMLButtonElement>) => {
|
||||
e.stopPropagation()
|
||||
e.nativeEvent.stopImmediatePropagation()
|
||||
onShowRetryResultList(retryDetail || [])
|
||||
}
|
||||
|
||||
return (
|
||||
<Button
|
||||
className='flex items-center justify-between mb-1 w-full'
|
||||
variant='tertiary'
|
||||
onClick={handleShowRetryResultList}
|
||||
>
|
||||
<div className='flex items-center'>
|
||||
<RiRestartFill className='mr-0.5 w-4 h-4 text-components-button-tertiary-text shrink-0' />
|
||||
{t('workflow.nodes.common.retry.retries', { num: retryDetail?.length })}
|
||||
</div>
|
||||
<RiArrowRightSLine className='w-4 h-4 text-components-button-tertiary-text shrink-0' />
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
export default RetryLogTrigger
|
||||
|
|
@ -6,7 +6,7 @@ import { useTranslation } from 'react-i18next'
|
|||
import {
|
||||
RiArrowLeftLine,
|
||||
} from '@remixicon/react'
|
||||
import TracingPanel from './tracing-panel'
|
||||
import TracingPanel from '../tracing-panel'
|
||||
import type { NodeTracing } from '@/types/workflow'
|
||||
|
||||
type Props = {
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
import RetryResultPanel from './retry-result-panel'
|
||||
import IterationResultPanel from './iteration-result-panel'
|
||||
import { RetryResultPanel } from './retry-log'
|
||||
import { IterationResultPanel } from './iteration-log'
|
||||
import { AgentResultPanel } from './agent-log'
|
||||
import type { IterationDurationMap, NodeTracing } from '@/types/workflow'
|
||||
|
||||
type SpecialResultPanelProps = {
|
||||
|
|
@ -11,6 +12,9 @@ type SpecialResultPanelProps = {
|
|||
setShowIteratingDetailFalse: () => void
|
||||
iterationResultList: NodeTracing[][]
|
||||
iterationResultDurationMap: IterationDurationMap
|
||||
|
||||
showAgentDetail: boolean
|
||||
setShowAgentDetailFalse: () => void
|
||||
}
|
||||
const SpecialResultPanel = ({
|
||||
showRetryDetail,
|
||||
|
|
@ -21,6 +25,9 @@ const SpecialResultPanel = ({
|
|||
setShowIteratingDetailFalse,
|
||||
iterationResultList,
|
||||
iterationResultDurationMap,
|
||||
|
||||
showAgentDetail,
|
||||
setShowAgentDetailFalse,
|
||||
}: SpecialResultPanelProps) => {
|
||||
return (
|
||||
<>
|
||||
|
|
@ -42,6 +49,13 @@ const SpecialResultPanel = ({
|
|||
/>
|
||||
)
|
||||
}
|
||||
{
|
||||
showAgentDetail && (
|
||||
<AgentResultPanel
|
||||
onBack={setShowAgentDetailFalse}
|
||||
/>
|
||||
)
|
||||
}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
import { BlockEnum } from '@/app/components/workflow/types'
|
||||
|
||||
export const agentNodeData = (() => {
|
||||
const node = {
|
||||
node_type: BlockEnum.Agent,
|
||||
execution_metadata: {
|
||||
agent_log: [
|
||||
{ id: '1', label: 'Root 1' },
|
||||
{ id: '2', parent_id: '1', label: 'Child 1.2' },
|
||||
{ id: '3', parent_id: '1', label: 'Child 1.3' },
|
||||
{ id: '4', parent_id: '2', label: 'Child 2.4' },
|
||||
{ id: '5', parent_id: '2', label: 'Child 2.5' },
|
||||
{ id: '6', parent_id: '3', label: 'Child 3.6' },
|
||||
{ id: '7', parent_id: '4', label: 'Child 4.7' },
|
||||
{ id: '8', parent_id: '4', label: 'Child 4.8' },
|
||||
{ id: '9', parent_id: '5', label: 'Child 5.9' },
|
||||
{ id: '10', parent_id: '5', label: 'Child 5.10' },
|
||||
{ id: '11', parent_id: '7', label: 'Child 7.11' },
|
||||
{ id: '12', parent_id: '7', label: 'Child 7.12' },
|
||||
{ id: '13', parent_id: '9', label: 'Child 9.13' },
|
||||
{ id: '14', parent_id: '9', label: 'Child 9.14' },
|
||||
{ id: '15', parent_id: '9', label: 'Child 9.15' },
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
return {
|
||||
in: [node],
|
||||
expect: [{
|
||||
...node,
|
||||
agentLog: [
|
||||
{
|
||||
id: '1',
|
||||
label: 'Root 1',
|
||||
children: [
|
||||
{
|
||||
id: '2',
|
||||
parent_id: '1',
|
||||
label: 'Child 1.2',
|
||||
children: [
|
||||
{
|
||||
id: '4',
|
||||
parent_id: '2',
|
||||
label: 'Child 2.4',
|
||||
children: [
|
||||
{
|
||||
id: '7',
|
||||
parent_id: '4',
|
||||
label: 'Child 4.7',
|
||||
children: [
|
||||
{ id: '11', parent_id: '7', label: 'Child 7.11' },
|
||||
{ id: '12', parent_id: '7', label: 'Child 7.12' },
|
||||
],
|
||||
},
|
||||
{ id: '8', parent_id: '4', label: 'Child 4.8' },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '5',
|
||||
parent_id: '2',
|
||||
label: 'Child 2.5',
|
||||
children: [
|
||||
{
|
||||
id: '9',
|
||||
parent_id: '5',
|
||||
label: 'Child 5.9',
|
||||
children: [
|
||||
{ id: '13', parent_id: '9', label: 'Child 9.13' },
|
||||
{ id: '14', parent_id: '9', label: 'Child 9.14' },
|
||||
{ id: '15', parent_id: '9', label: 'Child 9.15' },
|
||||
],
|
||||
},
|
||||
{ id: '10', parent_id: '5', label: 'Child 5.10' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
parent_id: '1',
|
||||
label: 'Child 1.3',
|
||||
children: [
|
||||
{ id: '6', parent_id: '3', label: 'Child 3.6' },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}],
|
||||
}
|
||||
})()
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import format from '.'
|
||||
import { agentNodeData } from './data'
|
||||
|
||||
describe('agent', () => {
|
||||
test('list should transform to tree', () => {
|
||||
// console.log(format(agentNodeData.in as any))
|
||||
expect(format(agentNodeData.in as any)).toEqual(agentNodeData.expect)
|
||||
})
|
||||
})
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
import { BlockEnum } from '@/app/components/workflow/types'
|
||||
import type { AgentLogItem, AgentLogItemWithChildren, NodeTracing } from '@/types/workflow'
|
||||
|
||||
const listToTree = (logs: AgentLogItem[]) => {
|
||||
if (!logs || logs.length === 0)
|
||||
return []
|
||||
|
||||
const tree: AgentLogItemWithChildren[] = []
|
||||
logs.forEach((log) => {
|
||||
const hasParent = !!log.parent_id
|
||||
if (hasParent) {
|
||||
const parent = logs.find(item => item.id === log.parent_id) as AgentLogItemWithChildren
|
||||
if (parent) {
|
||||
if (!parent.children)
|
||||
parent.children = []
|
||||
parent.children.push(log as AgentLogItemWithChildren)
|
||||
}
|
||||
}
|
||||
else {
|
||||
tree.push(log as AgentLogItemWithChildren)
|
||||
}
|
||||
})
|
||||
return tree
|
||||
}
|
||||
const format = (list: NodeTracing[]): NodeTracing[] => {
|
||||
const result: NodeTracing[] = list.map((item) => {
|
||||
if (item.node_type === BlockEnum.Agent && item.execution_metadata?.agent_log && item.execution_metadata?.agent_log.length > 0)
|
||||
item.agentLog = listToTree(item.execution_metadata.agent_log)
|
||||
|
||||
return item
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
export default format
|
||||
|
|
@ -1,8 +1,10 @@
|
|||
import formatToTracingNodeList from '.'
|
||||
import { simpleIterationData } from '../spec-test-data'
|
||||
import { simpleIterationData } from './iteration/data'
|
||||
import { simpleRetryData } from './retry/data'
|
||||
|
||||
describe('format api data to tracing panel data', () => {
|
||||
test('iteration should put nodes in details', () => {
|
||||
expect(formatToTracingNodeList(simpleIterationData.in as any)).toEqual(simpleIterationData.output)
|
||||
test('integration', () => {
|
||||
expect(formatToTracingNodeList(simpleIterationData.in.reverse() as any)).toEqual(simpleIterationData.expect)
|
||||
expect(formatToTracingNodeList(simpleRetryData.in.reverse() as any)).toEqual(simpleRetryData.expect)
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,101 +1,15 @@
|
|||
import type { NodeTracing } from '@/types/workflow'
|
||||
import { BlockEnum } from '../../../types'
|
||||
import formatIterationNode from './iteration'
|
||||
import formatRetryNode from './retry'
|
||||
import formatAgentNode from './agent'
|
||||
|
||||
type IterationNodeId = string
|
||||
type RunIndex = string
|
||||
type IterationGroupMap = Map<IterationNodeId, Map<RunIndex, NodeTracing[]>>
|
||||
|
||||
const processIterationNode = (item: NodeTracing) => {
|
||||
return {
|
||||
...item,
|
||||
details: [], // to add the sub nodes in the iteration
|
||||
}
|
||||
}
|
||||
|
||||
const updateParallelModeGroup = (nodeGroupMap: IterationGroupMap, runIndex: string, item: NodeTracing, iterationNode: NodeTracing) => {
|
||||
if (!nodeGroupMap.has(iterationNode.node_id))
|
||||
nodeGroupMap.set(iterationNode.node_id, new Map())
|
||||
|
||||
const groupMap = nodeGroupMap.get(iterationNode.node_id)!
|
||||
|
||||
if (!groupMap.has(runIndex))
|
||||
groupMap.set(runIndex, [item])
|
||||
|
||||
else
|
||||
groupMap.get(runIndex)!.push(item)
|
||||
|
||||
if (item.status === 'failed') {
|
||||
iterationNode.status = 'failed'
|
||||
iterationNode.error = item.error
|
||||
}
|
||||
|
||||
iterationNode.details = Array.from(groupMap.values())
|
||||
}
|
||||
|
||||
const updateSequentialModeGroup = (runIndex: number, item: NodeTracing, iterationNode: NodeTracing) => {
|
||||
const { details } = iterationNode
|
||||
if (details) {
|
||||
if (!details[runIndex])
|
||||
details[runIndex] = [item]
|
||||
else
|
||||
details[runIndex].push(item)
|
||||
}
|
||||
|
||||
if (item.status === 'failed') {
|
||||
iterationNode.status = 'failed'
|
||||
iterationNode.error = item.error
|
||||
}
|
||||
}
|
||||
|
||||
const addRetryDetail = (result: NodeTracing[], item: NodeTracing) => {
|
||||
const retryNode = result.find(node => node.node_id === item.node_id)
|
||||
|
||||
if (retryNode) {
|
||||
if (retryNode?.retryDetail)
|
||||
retryNode.retryDetail.push(item)
|
||||
else
|
||||
retryNode.retryDetail = [item]
|
||||
}
|
||||
}
|
||||
|
||||
const processNonIterationNode = (result: NodeTracing[], nodeGroupMap: IterationGroupMap, item: NodeTracing) => {
|
||||
const { execution_metadata } = item
|
||||
if (!execution_metadata?.iteration_id) {
|
||||
if (item.status === 'retry') {
|
||||
addRetryDetail(result, item)
|
||||
return
|
||||
}
|
||||
result.push(item)
|
||||
return
|
||||
}
|
||||
|
||||
const parentIterationNode = result.find(node => node.node_id === execution_metadata.iteration_id)
|
||||
const isInIteration = !!parentIterationNode && Array.isArray(parentIterationNode.details)
|
||||
if (!isInIteration)
|
||||
return
|
||||
|
||||
// the parallel in the iteration in mode.
|
||||
const { parallel_mode_run_id, iteration_index = 0 } = execution_metadata
|
||||
const isInParallel = !!parallel_mode_run_id
|
||||
|
||||
if (isInParallel)
|
||||
updateParallelModeGroup(nodeGroupMap, parallel_mode_run_id, item, parentIterationNode)
|
||||
else
|
||||
updateSequentialModeGroup(iteration_index, item, parentIterationNode)
|
||||
}
|
||||
|
||||
// list => tree. Put the iteration node's children into the details field.
|
||||
const formatToTracingNodeList = (list: NodeTracing[]) => {
|
||||
const allItems = [...list].reverse()
|
||||
const result: NodeTracing[] = []
|
||||
const iterationGroupMap = new Map<string, Map<string, NodeTracing[]>>()
|
||||
|
||||
allItems.forEach((item) => {
|
||||
item.node_type === BlockEnum.Iteration
|
||||
? result.push(processIterationNode(item))
|
||||
: processNonIterationNode(result, iterationGroupMap, item)
|
||||
})
|
||||
const formattedIterationList = formatIterationNode(allItems)
|
||||
const formattedRetryList = formatRetryNode(formattedIterationList)
|
||||
const formattedAgentList = formatAgentNode(formattedRetryList)
|
||||
|
||||
const result = formattedAgentList
|
||||
// console.log(allItems)
|
||||
// console.log(result)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,481 +0,0 @@
|
|||
export const simpleIterationData = {
|
||||
// start -> code(output: [1, 2, 3]) -> iteration(output: ['aaa', 'aaa', 'aaa']) -> end(output: ['aaa', 'aaa', 'aaa'])
|
||||
in: [
|
||||
{
|
||||
id: '36c9860a-39e6-4107-b750-655b07895f47',
|
||||
index: 1,
|
||||
predecessor_node_id: null,
|
||||
node_id: '1735023354069',
|
||||
node_type: 'start',
|
||||
title: 'Start',
|
||||
inputs: {
|
||||
'sys.files': [],
|
||||
'sys.user_id': '5ee03762-1d1a-46e8-ba0b-5f419a77da96',
|
||||
'sys.app_id': '8a5e87f8-6433-40f4-a67a-4be78a558dc7',
|
||||
'sys.workflow_id': 'bb5e2b89-40ac-45c9-9ccb-4f2cd926e080',
|
||||
'sys.workflow_run_id': '76adf675-a7d3-4cc1-9282-ed7ecfe4f65d',
|
||||
},
|
||||
process_data: null,
|
||||
outputs: {
|
||||
'sys.files': [],
|
||||
'sys.user_id': '5ee03762-1d1a-46e8-ba0b-5f419a77da96',
|
||||
'sys.app_id': '8a5e87f8-6433-40f4-a67a-4be78a558dc7',
|
||||
'sys.workflow_id': 'bb5e2b89-40ac-45c9-9ccb-4f2cd926e080',
|
||||
'sys.workflow_run_id': '76adf675-a7d3-4cc1-9282-ed7ecfe4f65d',
|
||||
},
|
||||
status: 'succeeded',
|
||||
error: null,
|
||||
elapsed_time: 0.011458,
|
||||
execution_metadata: null,
|
||||
extras: {},
|
||||
created_at: 1735023510,
|
||||
created_by_role: 'account',
|
||||
created_by_account: {
|
||||
id: '5ee03762-1d1a-46e8-ba0b-5f419a77da96',
|
||||
name: 'Joel',
|
||||
email: 'iamjoel007@gmail.com',
|
||||
},
|
||||
created_by_end_user: null,
|
||||
finished_at: 1735023510,
|
||||
},
|
||||
{
|
||||
id: 'a3105c5d-ff9e-44ea-9f4c-ab428958af20',
|
||||
index: 2,
|
||||
predecessor_node_id: '1735023354069',
|
||||
node_id: '1735023361224',
|
||||
node_type: 'code',
|
||||
title: 'Code',
|
||||
inputs: null,
|
||||
process_data: null,
|
||||
outputs: {
|
||||
result: [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
],
|
||||
},
|
||||
status: 'succeeded',
|
||||
error: null,
|
||||
elapsed_time: 0.103333,
|
||||
execution_metadata: null,
|
||||
extras: {},
|
||||
created_at: 1735023510,
|
||||
created_by_role: 'account',
|
||||
created_by_account: {
|
||||
id: '5ee03762-1d1a-46e8-ba0b-5f419a77da96',
|
||||
name: 'Joel',
|
||||
email: 'iamjoel007@gmail.com',
|
||||
},
|
||||
created_by_end_user: null,
|
||||
finished_at: 1735023511,
|
||||
},
|
||||
{
|
||||
id: 'a823134d-9f1a-45a4-8977-db838d076316',
|
||||
index: 3,
|
||||
predecessor_node_id: '1735023361224',
|
||||
node_id: '1735023391914',
|
||||
node_type: 'iteration',
|
||||
title: 'Iteration',
|
||||
inputs: null,
|
||||
process_data: null,
|
||||
outputs: {
|
||||
output: [
|
||||
'aaa',
|
||||
'aaa',
|
||||
'aaa',
|
||||
],
|
||||
},
|
||||
status: 'succeeded',
|
||||
error: null,
|
||||
elapsed_time: 0.408383,
|
||||
execution_metadata: {
|
||||
iteration_duration_map: {
|
||||
0: 0.118153,
|
||||
1: 0.135956,
|
||||
2: 0.128251,
|
||||
},
|
||||
total_tokens: 0,
|
||||
},
|
||||
extras: {},
|
||||
created_at: 1735023511,
|
||||
created_by_role: 'account',
|
||||
created_by_account: {
|
||||
id: '5ee03762-1d1a-46e8-ba0b-5f419a77da96',
|
||||
name: 'Joel',
|
||||
email: 'iamjoel007@gmail.com',
|
||||
},
|
||||
created_by_end_user: null,
|
||||
finished_at: 1735023511,
|
||||
},
|
||||
{
|
||||
id: 'a84a22d8-0f08-4006-bee2-fa7a7aef0420',
|
||||
index: 4,
|
||||
predecessor_node_id: '1735023391914start',
|
||||
node_id: '1735023409906',
|
||||
node_type: 'code',
|
||||
title: 'Code 2',
|
||||
inputs: null,
|
||||
process_data: null,
|
||||
outputs: {
|
||||
result: 'aaa',
|
||||
},
|
||||
status: 'succeeded',
|
||||
error: null,
|
||||
elapsed_time: 0.112688,
|
||||
execution_metadata: {
|
||||
iteration_id: '1735023391914',
|
||||
iteration_index: 0,
|
||||
},
|
||||
extras: {},
|
||||
created_at: 1735023511,
|
||||
created_by_role: 'account',
|
||||
created_by_account: {
|
||||
id: '5ee03762-1d1a-46e8-ba0b-5f419a77da96',
|
||||
name: 'Joel',
|
||||
email: 'iamjoel007@gmail.com',
|
||||
},
|
||||
created_by_end_user: null,
|
||||
finished_at: 1735023511,
|
||||
},
|
||||
{
|
||||
id: 'ff71d773-a916-4513-960f-d7dcc4fadd86',
|
||||
index: 5,
|
||||
predecessor_node_id: '1735023391914start',
|
||||
node_id: '1735023409906',
|
||||
node_type: 'code',
|
||||
title: 'Code 2',
|
||||
inputs: null,
|
||||
process_data: null,
|
||||
outputs: {
|
||||
result: 'aaa',
|
||||
},
|
||||
status: 'succeeded',
|
||||
error: null,
|
||||
elapsed_time: 0.126034,
|
||||
execution_metadata: {
|
||||
iteration_id: '1735023391914',
|
||||
iteration_index: 1,
|
||||
},
|
||||
extras: {},
|
||||
created_at: 1735023511,
|
||||
created_by_role: 'account',
|
||||
created_by_account: {
|
||||
id: '5ee03762-1d1a-46e8-ba0b-5f419a77da96',
|
||||
name: 'Joel',
|
||||
email: 'iamjoel007@gmail.com',
|
||||
},
|
||||
created_by_end_user: null,
|
||||
finished_at: 1735023511,
|
||||
},
|
||||
{
|
||||
id: 'd91c3ef9-0162-4013-9272-d4cc7fb1f188',
|
||||
index: 6,
|
||||
predecessor_node_id: '1735023391914start',
|
||||
node_id: '1735023409906',
|
||||
node_type: 'code',
|
||||
title: 'Code 2',
|
||||
inputs: null,
|
||||
process_data: null,
|
||||
outputs: {
|
||||
result: 'aaa',
|
||||
},
|
||||
status: 'succeeded',
|
||||
error: null,
|
||||
elapsed_time: 0.122716,
|
||||
execution_metadata: {
|
||||
iteration_id: '1735023391914',
|
||||
iteration_index: 2,
|
||||
},
|
||||
extras: {},
|
||||
created_at: 1735023511,
|
||||
created_by_role: 'account',
|
||||
created_by_account: {
|
||||
id: '5ee03762-1d1a-46e8-ba0b-5f419a77da96',
|
||||
name: 'Joel',
|
||||
email: 'iamjoel007@gmail.com',
|
||||
},
|
||||
created_by_end_user: null,
|
||||
finished_at: 1735023511,
|
||||
},
|
||||
{
|
||||
id: 'e6ad6560-1aa3-43f3-89e3-e5287c9ea272',
|
||||
index: 7,
|
||||
predecessor_node_id: '1735023391914',
|
||||
node_id: '1735023417757',
|
||||
node_type: 'end',
|
||||
title: 'End',
|
||||
inputs: {
|
||||
output: [
|
||||
'aaa',
|
||||
'aaa',
|
||||
'aaa',
|
||||
],
|
||||
},
|
||||
process_data: null,
|
||||
outputs: {
|
||||
output: [
|
||||
'aaa',
|
||||
'aaa',
|
||||
'aaa',
|
||||
],
|
||||
},
|
||||
status: 'succeeded',
|
||||
error: null,
|
||||
elapsed_time: 0.017552,
|
||||
execution_metadata: null,
|
||||
extras: {},
|
||||
created_at: 1735023511,
|
||||
created_by_role: 'account',
|
||||
created_by_account: {
|
||||
id: '5ee03762-1d1a-46e8-ba0b-5f419a77da96',
|
||||
name: 'Joel',
|
||||
email: 'iamjoel007@gmail.com',
|
||||
},
|
||||
created_by_end_user: null,
|
||||
finished_at: 1735023511,
|
||||
},
|
||||
].reverse(),
|
||||
output: [
|
||||
{
|
||||
id: '36c9860a-39e6-4107-b750-655b07895f47',
|
||||
index: 1,
|
||||
predecessor_node_id: null,
|
||||
node_id: '1735023354069',
|
||||
node_type: 'start',
|
||||
title: 'Start',
|
||||
inputs: {
|
||||
'sys.files': [],
|
||||
'sys.user_id': '5ee03762-1d1a-46e8-ba0b-5f419a77da96',
|
||||
'sys.app_id': '8a5e87f8-6433-40f4-a67a-4be78a558dc7',
|
||||
'sys.workflow_id': 'bb5e2b89-40ac-45c9-9ccb-4f2cd926e080',
|
||||
'sys.workflow_run_id': '76adf675-a7d3-4cc1-9282-ed7ecfe4f65d',
|
||||
},
|
||||
process_data: null,
|
||||
outputs: {
|
||||
'sys.files': [],
|
||||
'sys.user_id': '5ee03762-1d1a-46e8-ba0b-5f419a77da96',
|
||||
'sys.app_id': '8a5e87f8-6433-40f4-a67a-4be78a558dc7',
|
||||
'sys.workflow_id': 'bb5e2b89-40ac-45c9-9ccb-4f2cd926e080',
|
||||
'sys.workflow_run_id': '76adf675-a7d3-4cc1-9282-ed7ecfe4f65d',
|
||||
},
|
||||
status: 'succeeded',
|
||||
error: null,
|
||||
elapsed_time: 0.011458,
|
||||
execution_metadata: null,
|
||||
extras: {},
|
||||
created_at: 1735023510,
|
||||
created_by_role: 'account',
|
||||
created_by_account: {
|
||||
id: '5ee03762-1d1a-46e8-ba0b-5f419a77da96',
|
||||
name: 'Joel',
|
||||
email: 'iamjoel007@gmail.com',
|
||||
},
|
||||
created_by_end_user: null,
|
||||
finished_at: 1735023510,
|
||||
},
|
||||
{
|
||||
id: 'a3105c5d-ff9e-44ea-9f4c-ab428958af20',
|
||||
index: 2,
|
||||
predecessor_node_id: '1735023354069',
|
||||
node_id: '1735023361224',
|
||||
node_type: 'code',
|
||||
title: 'Code',
|
||||
inputs: null,
|
||||
process_data: null,
|
||||
outputs: {
|
||||
result: [
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
],
|
||||
},
|
||||
status: 'succeeded',
|
||||
error: null,
|
||||
elapsed_time: 0.103333,
|
||||
execution_metadata: null,
|
||||
extras: {},
|
||||
created_at: 1735023510,
|
||||
created_by_role: 'account',
|
||||
created_by_account: {
|
||||
id: '5ee03762-1d1a-46e8-ba0b-5f419a77da96',
|
||||
name: 'Joel',
|
||||
email: 'iamjoel007@gmail.com',
|
||||
},
|
||||
created_by_end_user: null,
|
||||
finished_at: 1735023511,
|
||||
},
|
||||
{
|
||||
id: 'a823134d-9f1a-45a4-8977-db838d076316',
|
||||
index: 3,
|
||||
predecessor_node_id: '1735023361224',
|
||||
node_id: '1735023391914',
|
||||
node_type: 'iteration',
|
||||
title: 'Iteration',
|
||||
inputs: null,
|
||||
process_data: null,
|
||||
outputs: {
|
||||
output: [
|
||||
'aaa',
|
||||
'aaa',
|
||||
'aaa',
|
||||
],
|
||||
},
|
||||
status: 'succeeded',
|
||||
error: null,
|
||||
elapsed_time: 0.408383,
|
||||
execution_metadata: {
|
||||
iteration_duration_map: {
|
||||
0: 0.118153,
|
||||
1: 0.135956,
|
||||
2: 0.128251,
|
||||
},
|
||||
total_tokens: 0,
|
||||
},
|
||||
extras: {},
|
||||
created_at: 1735023511,
|
||||
created_by_role: 'account',
|
||||
created_by_account: {
|
||||
id: '5ee03762-1d1a-46e8-ba0b-5f419a77da96',
|
||||
name: 'Joel',
|
||||
email: 'iamjoel007@gmail.com',
|
||||
},
|
||||
created_by_end_user: null,
|
||||
finished_at: 1735023511,
|
||||
details: [
|
||||
[
|
||||
{
|
||||
id: 'a84a22d8-0f08-4006-bee2-fa7a7aef0420',
|
||||
index: 4,
|
||||
predecessor_node_id: '1735023391914start',
|
||||
node_id: '1735023409906',
|
||||
node_type: 'code',
|
||||
title: 'Code 2',
|
||||
inputs: null,
|
||||
process_data: null,
|
||||
outputs: {
|
||||
result: 'aaa',
|
||||
},
|
||||
status: 'succeeded',
|
||||
error: null,
|
||||
elapsed_time: 0.112688,
|
||||
execution_metadata: {
|
||||
iteration_id: '1735023391914',
|
||||
iteration_index: 0,
|
||||
},
|
||||
extras: {},
|
||||
created_at: 1735023511,
|
||||
created_by_role: 'account',
|
||||
created_by_account: {
|
||||
id: '5ee03762-1d1a-46e8-ba0b-5f419a77da96',
|
||||
name: 'Joel',
|
||||
email: 'iamjoel007@gmail.com',
|
||||
},
|
||||
created_by_end_user: null,
|
||||
finished_at: 1735023511,
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
id: 'ff71d773-a916-4513-960f-d7dcc4fadd86',
|
||||
index: 5,
|
||||
predecessor_node_id: '1735023391914start',
|
||||
node_id: '1735023409906',
|
||||
node_type: 'code',
|
||||
title: 'Code 2',
|
||||
inputs: null,
|
||||
process_data: null,
|
||||
outputs: {
|
||||
result: 'aaa',
|
||||
},
|
||||
status: 'succeeded',
|
||||
error: null,
|
||||
elapsed_time: 0.126034,
|
||||
execution_metadata: {
|
||||
iteration_id: '1735023391914',
|
||||
iteration_index: 1,
|
||||
},
|
||||
extras: {},
|
||||
created_at: 1735023511,
|
||||
created_by_role: 'account',
|
||||
created_by_account: {
|
||||
id: '5ee03762-1d1a-46e8-ba0b-5f419a77da96',
|
||||
name: 'Joel',
|
||||
email: 'iamjoel007@gmail.com',
|
||||
},
|
||||
created_by_end_user: null,
|
||||
finished_at: 1735023511,
|
||||
},
|
||||
],
|
||||
[
|
||||
{
|
||||
id: 'd91c3ef9-0162-4013-9272-d4cc7fb1f188',
|
||||
index: 6,
|
||||
predecessor_node_id: '1735023391914start',
|
||||
node_id: '1735023409906',
|
||||
node_type: 'code',
|
||||
title: 'Code 2',
|
||||
inputs: null,
|
||||
process_data: null,
|
||||
outputs: {
|
||||
result: 'aaa',
|
||||
},
|
||||
status: 'succeeded',
|
||||
error: null,
|
||||
elapsed_time: 0.122716,
|
||||
execution_metadata: {
|
||||
iteration_id: '1735023391914',
|
||||
iteration_index: 2,
|
||||
},
|
||||
extras: {},
|
||||
created_at: 1735023511,
|
||||
created_by_role: 'account',
|
||||
created_by_account: {
|
||||
id: '5ee03762-1d1a-46e8-ba0b-5f419a77da96',
|
||||
name: 'Joel',
|
||||
email: 'iamjoel007@gmail.com',
|
||||
},
|
||||
created_by_end_user: null,
|
||||
finished_at: 1735023511,
|
||||
},
|
||||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'e6ad6560-1aa3-43f3-89e3-e5287c9ea272',
|
||||
index: 7,
|
||||
predecessor_node_id: '1735023391914',
|
||||
node_id: '1735023417757',
|
||||
node_type: 'end',
|
||||
title: 'End',
|
||||
inputs: {
|
||||
output: [
|
||||
'aaa',
|
||||
'aaa',
|
||||
'aaa',
|
||||
],
|
||||
},
|
||||
process_data: null,
|
||||
outputs: {
|
||||
output: [
|
||||
'aaa',
|
||||
'aaa',
|
||||
'aaa',
|
||||
],
|
||||
},
|
||||
status: 'succeeded',
|
||||
error: null,
|
||||
elapsed_time: 0.017552,
|
||||
execution_metadata: null,
|
||||
extras: {},
|
||||
created_at: 1735023511,
|
||||
created_by_role: 'account',
|
||||
created_by_account: {
|
||||
id: '5ee03762-1d1a-46e8-ba0b-5f419a77da96',
|
||||
name: 'Joel',
|
||||
email: 'iamjoel007@gmail.com',
|
||||
},
|
||||
created_by_end_user: null,
|
||||
finished_at: 1735023511,
|
||||
},
|
||||
],
|
||||
}
|
||||
|
|
@ -24,7 +24,8 @@ export const useInvalidateStrategyProviders = () => {
|
|||
export const useStrategyProviderDetail = (agentProvider: string) => {
|
||||
return useQuery<StrategyPluginDetail>({
|
||||
queryKey: [NAME_SPACE, 'detail', agentProvider],
|
||||
queryFn: () => get<StrategyPluginDetail>(`/workspaces/current/agent-providers/${agentProvider}`),
|
||||
queryFn: () => get<StrategyPluginDetail>(`/workspaces/current/agent-provider/${agentProvider}`),
|
||||
enabled: !!agentProvider,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,20 @@ import type {
|
|||
import type { TransferMethod } from '@/types/app'
|
||||
import type { ErrorHandleTypeEnum } from '@/app/components/workflow/nodes/_base/components/error-handle/types'
|
||||
|
||||
export type AgentLogItem = {
|
||||
node_execution_id: string,
|
||||
id: string,
|
||||
parent_id?: string,
|
||||
label: string,
|
||||
data: object, // debug data
|
||||
error?: string,
|
||||
status: string,
|
||||
}
|
||||
|
||||
export type AgentLogItemWithChildren = AgentLogItem & {
|
||||
children: AgentLogItemWithChildren[]
|
||||
}
|
||||
|
||||
export type NodeTracing = {
|
||||
id: string
|
||||
index: number
|
||||
|
|
@ -36,6 +50,7 @@ export type NodeTracing = {
|
|||
parallel_mode_run_id?: string
|
||||
iteration_duration_map?: IterationDurationMap
|
||||
error_strategy?: ErrorHandleTypeEnum
|
||||
agent_log?: AgentLogItem[]
|
||||
}
|
||||
metadata: {
|
||||
iterator_length: number
|
||||
|
|
@ -53,6 +68,7 @@ export type NodeTracing = {
|
|||
expand?: boolean // for UI
|
||||
details?: NodeTracing[][] // iteration detail
|
||||
retryDetail?: NodeTracing[] // retry detail
|
||||
agentLog?: AgentLogItemWithChildren[]
|
||||
parallel_id?: string
|
||||
parallel_start_node_id?: string
|
||||
parent_parallel_id?: string
|
||||
|
|
|
|||
Loading…
Reference in New Issue