diff --git a/web/app/components/base/list-empty/index.tsx b/web/app/components/base/list-empty/index.tsx index e925878bc1..c295ffbaec 100644 --- a/web/app/components/base/list-empty/index.tsx +++ b/web/app/components/base/list-empty/index.tsx @@ -1,3 +1,4 @@ +import type { ReactNode } from 'react' import React from 'react' import { Variable02 } from '../icons/src/vender/solid/development' import VerticalLine from './vertical-line' @@ -5,19 +6,21 @@ import HorizontalLine from './horizontal-line' type ListEmptyProps = { title?: string - description?: React.ReactNode + description?: ReactNode + icon?: ReactNode } const ListEmpty = ({ title, description, + icon, }: ListEmptyProps) => { return (
- + {icon || } diff --git a/web/app/components/workflow/block-icon.tsx b/web/app/components/workflow/block-icon.tsx index 3656c42b3f..7f7aeca092 100644 --- a/web/app/components/workflow/block-icon.tsx +++ b/web/app/components/workflow/block-icon.tsx @@ -2,6 +2,7 @@ import type { FC } from 'react' import { memo } from 'react' import { BlockEnum } from './types' import { + Agent, Answer, Assigner, Code, @@ -53,8 +54,7 @@ const getIcon = (type: BlockEnum, className: string) => { [BlockEnum.ParameterExtractor]: , [BlockEnum.DocExtractor]: , [BlockEnum.ListFilter]: , - // TODO: add icon for Agent - [BlockEnum.Agent]: , + [BlockEnum.Agent]: , }[type] } const ICON_CONTAINER_BG_COLOR_MAP: Record = { diff --git a/web/app/components/workflow/nodes/_base/components/agent-strategy-selector.tsx b/web/app/components/workflow/nodes/_base/components/agent-strategy-selector.tsx index 8976289149..ed506c63f3 100644 --- a/web/app/components/workflow/nodes/_base/components/agent-strategy-selector.tsx +++ b/web/app/components/workflow/nodes/_base/components/agent-strategy-selector.tsx @@ -48,6 +48,7 @@ export const AgentStrategySelector = (props: AgentStrategySelectorProps) => { }, [query, list.data]) // TODO: should be replaced by real data const isExternalInstalled = true + const { t } = useTranslation() return
setOpen(o => !o)}> @@ -64,7 +65,7 @@ export const AgentStrategySelector = (props: AgentStrategySelectorProps) => {

- {value?.agent_strategy_name || 'Select agentic strategy'} + {value?.agent_strategy_name || t('workflow.nodes.agent.strategy.selectTip')}

{value &&
e.stopPropagation()} size={'small'} /> diff --git a/web/app/components/workflow/nodes/_base/components/agent-strategy.tsx b/web/app/components/workflow/nodes/_base/components/agent-strategy.tsx index 636baaa08b..50bf260311 100644 --- a/web/app/components/workflow/nodes/_base/components/agent-strategy.tsx +++ b/web/app/components/workflow/nodes/_base/components/agent-strategy.tsx @@ -5,6 +5,7 @@ import { AgentStrategySelector } from './agent-strategy-selector' import Link from 'next/link' import { useTranslation } from 'react-i18next' import Form from '@/app/components/header/account-setting/model-provider-page/model-modal/Form' +import { Agent } from '@/app/components/base/icons/src/vender/workflow' export type Strategy = { agent_strategy_provider_name: string @@ -39,8 +40,8 @@ export const AgentStrategy = (props: AgentStrategyProps) => { fieldLabelClassName='uppercase' />
- // TODO: list empty need a icon : } title={t('workflow.nodes.agent.strategy.configureTip')} description={
{t('workflow.nodes.agent.strategy.configureTipDesc')}
diff --git a/web/app/components/workflow/nodes/agent/node.tsx b/web/app/components/workflow/nodes/agent/node.tsx index dbc968de93..ea51cbb0ff 100644 --- a/web/app/components/workflow/nodes/agent/node.tsx +++ b/web/app/components/workflow/nodes/agent/node.tsx @@ -6,18 +6,26 @@ import ModelSelector from '@/app/components/header/account-setting/model-provide import { Group, GroupLabel } from '../_base/components/group' import { ToolIcon } from './components/tool-icon' import useConfig from './use-config' +import { useTranslation } from 'react-i18next' const AgentNode: FC> = (props) => { const { inputs } = useConfig(props.id, props.data) + const { t } = useTranslation() return
{inputs.agent_strategy_name - ? + ? {inputs.agent_strategy_name} - : } + : } - Model + {t('workflow.nodes.agent.model')} } > > = (props) => { /> - Toolbox + {t('workflow.nodes.agent.toolbox')} }>
- - + +
diff --git a/web/app/components/workflow/nodes/agent/panel.tsx b/web/app/components/workflow/nodes/agent/panel.tsx index 277c745fe1..3c9c10d9ae 100644 --- a/web/app/components/workflow/nodes/agent/panel.tsx +++ b/web/app/components/workflow/nodes/agent/panel.tsx @@ -4,8 +4,9 @@ import type { AgentNodeType } from './types' import Field from '../_base/components/field' import { InputNumber } from '@/app/components/base/input-number' import Slider from '@/app/components/base/slider' -import useNodeCrud from '../_base/hooks/use-node-crud' import { AgentStrategy } from '../_base/components/agent-strategy' +import useConfig from './use-config' +import { useTranslation } from 'react-i18next' const mockSchema = [ { @@ -260,7 +261,8 @@ const mockSchema = [ ] as const const AgentPanel: FC> = (props) => { - const { inputs, setInputs } = useNodeCrud(props.id, props.data) + const { inputs, setInputs } = useConfig(props.id, props.data) + const { t } = useTranslation() const [iter, setIter] = [inputs.max_iterations, (value: number) => { setInputs({ ...inputs, @@ -268,7 +270,7 @@ const AgentPanel: FC> = (props) => { }) }] return
- + > = (props) => { })} /> - + - +
{ return { readOnly, inputs, + setInputs, handleVarListChange, handleAddVariable, } diff --git a/web/app/components/workflow/run/utils/format-log/iteration/index.spec.ts b/web/app/components/workflow/run/utils/format-log/iteration/index.spec.ts index 4bcbcf53e8..245263ef4a 100644 --- a/web/app/components/workflow/run/utils/format-log/iteration/index.spec.ts +++ b/web/app/components/workflow/run/utils/format-log/iteration/index.spec.ts @@ -2,8 +2,9 @@ import format from '.' import { simpleIterationData } from './data' describe('format api data to tracing panel data', () => { - // test('result should have no nodes in iteration node', () => { - // } + test('result should have no nodes in iteration node', () => { + expect(format(simpleIterationData.in as any).find(item => !!(item as any).execution_metadata?.iteration_id)).toBeUndefined() + }) test('iteration should put nodes in details', () => { expect(format(simpleIterationData.in as any)).toEqual(simpleIterationData.output) }) diff --git a/web/app/components/workflow/run/utils/format-log/iteration/index.ts b/web/app/components/workflow/run/utils/format-log/iteration/index.ts index 731f1ca3f5..7583f40b1a 100644 --- a/web/app/components/workflow/run/utils/format-log/iteration/index.ts +++ b/web/app/components/workflow/run/utils/format-log/iteration/index.ts @@ -31,6 +31,11 @@ const format = (list: NodeTracing[]): NodeTracing[] => { .map((item) => { if (item.node_type === BlockEnum.Iteration) { const childrenNodes = list.filter(child => child.execution_metadata?.iteration_id === item.node_id) + const error = childrenNodes.find(child => child.status === 'failed') + if (error) { + item.status = 'failed' + item.error = error.error + } return addChildrenToIterationNode(item, childrenNodes) } diff --git a/web/app/components/workflow/run/utils/format-log/retry/index.ts b/web/app/components/workflow/run/utils/format-log/retry/index.ts index e69de29bb2..37e68099d6 100644 --- a/web/app/components/workflow/run/utils/format-log/retry/index.ts +++ b/web/app/components/workflow/run/utils/format-log/retry/index.ts @@ -0,0 +1,7 @@ +import type { NodeTracing } from '@/types/workflow' + +const format = (list: NodeTracing[]): NodeTracing[] => { + return list +} + +export default format diff --git a/web/i18n/en-US/workflow.ts b/web/i18n/en-US/workflow.ts index 2566dc67e5..64339e8c03 100644 --- a/web/i18n/en-US/workflow.ts +++ b/web/i18n/en-US/workflow.ts @@ -699,8 +699,11 @@ const translation = { }, agent: { strategy: { + label: 'Agentic Strategy', + shortLabel: 'Strategy', configureTip: 'Please configure agentic strategy.', configureTipDesc: 'After configuring the agentic strategy, this node will automatically load the remaining configurations. The strategy will affect the mechanism of multi-step tool reasoning. ', + selectTip: 'Select agentic strategy', }, learnMore: 'Learn more', pluginNotInstalled: 'This plugin is not installed', @@ -710,6 +713,15 @@ const translation = { install: 'Install', installing: 'Installing', }, + model: 'model', + toolbox: 'toolbox', + strategyNotSet: 'Agentic strategy Not Set', + tools: 'Tools', + maxIterations: 'Max Iterations', + modelNotInstallTooltip: 'This model is not installed', + toolNotInstallTooltip: '{{tool}} is not installed', + toolNotAuthorizedTooltip: '{{tool}} Not Authorized', + strategyNotInstallTooltip: '{{strategy}} is not installed', }, }, tracing: { diff --git a/web/i18n/zh-Hans/workflow.ts b/web/i18n/zh-Hans/workflow.ts index f2e1cf4881..731b27e9c2 100644 --- a/web/i18n/zh-Hans/workflow.ts +++ b/web/i18n/zh-Hans/workflow.ts @@ -699,8 +699,11 @@ const translation = { }, agent: { strategy: { + label: 'Agent 策略', + shortLabel: '策略', configureTip: '请配置 Agent 策略。', configureTipDesc: '配置完成后,此节点将自动加载剩余配置。策略将影响多步工具推理的机制。', + selectTip: '选择 Agent 策略', }, learnMore: '了解更多', pluginNotInstalled: '插件未安装', @@ -710,6 +713,15 @@ const translation = { install: '安装', installing: '安装中', }, + model: '模型', + toolbox: '工具箱', + strategyNotSet: '代理策略未设置', + tools: '工具', + maxIterations: '最大迭代次数', + modelNotInstallTooltip: '此模型未安装', + toolNotInstallTooltip: '{{tool}} 未安装', + toolNotAuthorizedTooltip: '{{tool}} 未授权', + strategyNotInstallTooltip: '{{strategy}} 未安装', }, }, tracing: {