From 0a300183306a7479b401406f8a9f021145fcba12 Mon Sep 17 00:00:00 2001 From: Joel Date: Mon, 30 Dec 2024 18:27:49 +0800 Subject: [PATCH] chore: one step circle check --- .../run/utils/format-log/agent/data.ts | 63 ++++++++++++++++++- .../run/utils/format-log/agent/index.spec.ts | 10 ++- .../run/utils/format-log/agent/index.ts | 41 +++++++++++- web/types/workflow.ts | 1 + 4 files changed, 109 insertions(+), 6 deletions(-) diff --git a/web/app/components/workflow/run/utils/format-log/agent/data.ts b/web/app/components/workflow/run/utils/format-log/agent/data.ts index 828a482e9d..a159fc2832 100644 --- a/web/app/components/workflow/run/utils/format-log/agent/data.ts +++ b/web/app/components/workflow/run/utils/format-log/agent/data.ts @@ -1,4 +1,5 @@ import { BlockEnum } from '@/app/components/workflow/types' +import { has } from 'immer/dist/internal' export const agentNodeData = (() => { const node = { @@ -114,14 +115,70 @@ export const oneStepCircle = (() => { id: '1', label: 'Node 1', hasCircle: true, + children: [], + }, + ], + }], + } + +})() + +export const multiStepsCircle = (() => { + const node = { + node_type: BlockEnum.Agent, + execution_metadata: { + agent_log: [ + // 1 -> [2 -> 4 -> 1, 3] + { id: '1', label: 'Node 1' }, + { id: '2', parent_id: '1', label: 'Node 2' }, + { id: '3', parent_id: '1', label: 'Node 3' }, + { id: '4', parent_id: '2', label: 'Node 4' }, + // Loop + { id: '1', parent_id: '1', label: 'Node 1' }, + { id: '2', parent_id: '1', label: 'Node 2' }, + { id: '4', parent_id: '2', label: 'Node 4' }, + // { id: '1', parent_id: '1', label: 'Node 1' }, + // { id: '2', parent_id: '1', label: 'Node 2' }, + // { id: '4', parent_id: '2', label: 'Node 4' }, + + ], + }, + } + + return { + in: [node], + expect: [{ + ...node, + agentLog: [ + { + id: '1', + label: 'Node 1', + children: [ + { + id: '2', + parent_id: '1', + label: 'Node 2', + children: [ + { + id: '4', + parent_id: '2', + label: 'Node 4', + children: [], + hasCircle: true, + } + ], + }, + { + id: '3', + parent_id: '1', + label: 'Node 3', + }, + ], }, ], }], } })() -export const multiStepsCircle = () => { -} - export const CircleNestCircle = (() => { })() diff --git a/web/app/components/workflow/run/utils/format-log/agent/index.spec.ts b/web/app/components/workflow/run/utils/format-log/agent/index.spec.ts index 0fd871c41d..e211744bbe 100644 --- a/web/app/components/workflow/run/utils/format-log/agent/index.spec.ts +++ b/web/app/components/workflow/run/utils/format-log/agent/index.spec.ts @@ -1,9 +1,17 @@ +import exp from 'constants' import format from '.' -import { agentNodeData } from './data' +import { agentNodeData, oneStepCircle, multiStepsCircle } 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) }) + + test('list should remove circle log item', () => { + // format(oneStepCircle.in as any) + console.log(JSON.stringify(format(multiStepsCircle.in as any)[0].agentLog)) + // expect(format(oneStepCircle.in as any)).toEqual(oneStepCircle.expect) + // expect(format(multiStepsCircle.in as any)).toEqual(multiStepsCircle.expect) + }) }) diff --git a/web/app/components/workflow/run/utils/format-log/agent/index.ts b/web/app/components/workflow/run/utils/format-log/agent/index.ts index 2efa44114c..8d95c76f24 100644 --- a/web/app/components/workflow/run/utils/format-log/agent/index.ts +++ b/web/app/components/workflow/run/utils/format-log/agent/index.ts @@ -1,10 +1,43 @@ import { BlockEnum } from '@/app/components/workflow/types' import type { AgentLogItem, AgentLogItemWithChildren, NodeTracing } from '@/types/workflow' +import { cloneDeep } from 'lodash-es' const supportedAgentLogNodes = [BlockEnum.Agent, BlockEnum.Tool] -const removeCircle = (node: NodeTracing) => { +const remove = (node: AgentLogItemWithChildren, removeId: string) => { + const { children } = node + if (!children || children.length === 0) { + return + } + children.forEach((child, index) => { + if (child.id === removeId) { + node.hasCircle = true + children.splice(index, 1) + return + } + remove(child, removeId) + }) +} +const removeCircleLogItem = (log: AgentLogItemWithChildren) => { + let newLog = cloneDeep(log) + let { id, children } = newLog + if (!children || children.length === 0) { + return log + } + // check one step circle + const hasOneStepCircle = !!children.find(c => c.id === id) + if (hasOneStepCircle) { + newLog.hasCircle = true + newLog.children = newLog.children.filter(c => c.id !== id) + children = newLog.children + } + + children.forEach((child, index) => { + remove(child, id) // check multi steps circle + children[index] = removeCircleLogItem(child) + }) + return newLog } const listToTree = (logs: AgentLogItem[]) => { @@ -31,8 +64,12 @@ const listToTree = (logs: AgentLogItem[]) => { const format = (list: NodeTracing[]): NodeTracing[] => { const result: NodeTracing[] = list.map((item) => { + let treeList: AgentLogItemWithChildren[] = [] + let removedCircleTree: AgentLogItemWithChildren[] = [] if (supportedAgentLogNodes.includes(item.node_type) && item.execution_metadata?.agent_log && item.execution_metadata?.agent_log.length > 0) - item.agentLog = listToTree(item.execution_metadata.agent_log) + treeList = listToTree(item.execution_metadata.agent_log) + removedCircleTree = treeList.length > 0 ? treeList.map(t => removeCircleLogItem(t)) : [] + item.agentLog = removedCircleTree return item }) diff --git a/web/types/workflow.ts b/web/types/workflow.ts index 1efde98b3d..3ac1db9715 100644 --- a/web/types/workflow.ts +++ b/web/types/workflow.ts @@ -20,6 +20,7 @@ export type AgentLogItem = { } export type AgentLogItemWithChildren = AgentLogItem & { + hasCircle?: boolean children: AgentLogItemWithChildren[] }