### What problem does this PR solve? Feat: Allow operators inside the loop operator to reference the output parameters of external operators #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.20.0
| export const initialIterationValues = { | export const initialIterationValues = { | ||||
| items_ref: '', | items_ref: '', | ||||
| }; | }; | ||||
| export const initialIterationStartValues = {}; | |||||
| export const initialIterationStartValues = { | |||||
| outputs: { | |||||
| item: { | |||||
| type: 'unkown', | |||||
| }, | |||||
| index: { | |||||
| type: 'integer', | |||||
| }, | |||||
| }, | |||||
| }; | |||||
| export const initialCodeValues = { | export const initialCodeValues = { | ||||
| lang: 'python', | lang: 'python', |
| import { LlmSettingSchema } from '@/components/llm-setting-items/next'; | import { LlmSettingSchema } from '@/components/llm-setting-items/next'; | ||||
| import { CodeTemplateStrMap, ProgrammingLanguage } from '@/constants/agent'; | import { CodeTemplateStrMap, ProgrammingLanguage } from '@/constants/agent'; | ||||
| import IterationStartForm from '@/pages/flow/form/iteration-start-from'; | |||||
| import { useTranslation } from 'react-i18next'; | import { useTranslation } from 'react-i18next'; | ||||
| import { z } from 'zod'; | import { z } from 'zod'; | ||||
| import { Operator } from '../constant'; | import { Operator } from '../constant'; | ||||
| import GoogleScholarForm from '../form/google-scholar-form'; | import GoogleScholarForm from '../form/google-scholar-form'; | ||||
| import InvokeForm from '../form/invoke-form'; | import InvokeForm from '../form/invoke-form'; | ||||
| import IterationForm from '../form/iteration-form'; | import IterationForm from '../form/iteration-form'; | ||||
| import IterationStartForm from '../form/iteration-start-from'; | |||||
| import Jin10Form from '../form/jin10-form'; | import Jin10Form from '../form/jin10-form'; | ||||
| import KeywordExtractForm from '../form/keyword-extract-form'; | import KeywordExtractForm from '../form/keyword-extract-form'; | ||||
| import MessageForm from '../form/message-form'; | import MessageForm from '../form/message-form'; |
| initialGoogleScholarValues, | initialGoogleScholarValues, | ||||
| initialGoogleValues, | initialGoogleValues, | ||||
| initialInvokeValues, | initialInvokeValues, | ||||
| initialIterationStartValues, | |||||
| initialIterationValues, | initialIterationValues, | ||||
| initialJin10Values, | initialJin10Values, | ||||
| initialKeywordExtractValues, | initialKeywordExtractValues, | ||||
| [Operator.Template]: initialTemplateValues, | [Operator.Template]: initialTemplateValues, | ||||
| [Operator.Email]: initialEmailValues, | [Operator.Email]: initialEmailValues, | ||||
| [Operator.Iteration]: initialIterationValues, | [Operator.Iteration]: initialIterationValues, | ||||
| [Operator.IterationStart]: initialIterationValues, | |||||
| [Operator.IterationStart]: initialIterationStartValues, | |||||
| [Operator.Code]: initialCodeValues, | [Operator.Code]: initialCodeValues, | ||||
| [Operator.WaitingDialogue]: initialWaitingDialogueValues, | [Operator.WaitingDialogue]: initialWaitingDialogueValues, | ||||
| [Operator.Agent]: { ...initialAgentValues, llm_id: llmId }, | [Operator.Agent]: { ...initialAgentValues, llm_id: llmId }, | ||||
| ); | ); | ||||
| } | } | ||||
| function useResizeIterationNode() { | |||||
| const { getNode, nodes, updateNode } = useGraphStore((state) => state); | |||||
| const resizeIterationNode = useCallback( | |||||
| (type: string, position: Position, parentId?: string) => { | |||||
| const parentNode = getNode(parentId); | |||||
| if (parentNode && !isBottomSubAgent(type, position)) { | |||||
| const MoveRightDistance = 310; | |||||
| const childNodeList = nodes.filter((x) => x.parentId === parentId); | |||||
| const maxX = Math.max(...childNodeList.map((x) => x.position.x)); | |||||
| if (maxX + MoveRightDistance > parentNode.position.x) { | |||||
| updateNode({ | |||||
| ...parentNode, | |||||
| width: (parentNode.width || 0) + MoveRightDistance, | |||||
| position: { | |||||
| x: parentNode.position.x + MoveRightDistance / 2, | |||||
| y: parentNode.position.y, | |||||
| }, | |||||
| }); | |||||
| } | |||||
| } | |||||
| }, | |||||
| [getNode, nodes, updateNode], | |||||
| ); | |||||
| return { resizeIterationNode }; | |||||
| } | |||||
| export function useAddNode(reactFlowInstance?: ReactFlowInstance<any, any>) { | export function useAddNode(reactFlowInstance?: ReactFlowInstance<any, any>) { | ||||
| const { edges, nodes, addEdge, addNode, getNode, updateNode } = useGraphStore( | const { edges, nodes, addEdge, addNode, getNode, updateNode } = useGraphStore( | ||||
| (state) => state, | (state) => state, | ||||
| const { calculateNewlyBackChildPosition } = useCalculateNewlyChildPosition(); | const { calculateNewlyBackChildPosition } = useCalculateNewlyChildPosition(); | ||||
| const { addChildEdge } = useAddChildEdge(); | const { addChildEdge } = useAddChildEdge(); | ||||
| const { addToolNode } = useAddToolNode(); | const { addToolNode } = useAddToolNode(); | ||||
| const { resizeIterationNode } = useResizeIterationNode(); | |||||
| // const [reactFlowInstance, setReactFlowInstance] = | // const [reactFlowInstance, setReactFlowInstance] = | ||||
| // useState<ReactFlowInstance<any, any>>(); | // useState<ReactFlowInstance<any, any>>(); | ||||
| newNode.extent = 'parent'; | newNode.extent = 'parent'; | ||||
| const parentNode = getNode(node.parentId); | const parentNode = getNode(node.parentId); | ||||
| if (parentNode && !isBottomSubAgent(type, params.position)) { | if (parentNode && !isBottomSubAgent(type, params.position)) { | ||||
| const MoveRightDistance = 310; | |||||
| updateNode({ | |||||
| ...parentNode, | |||||
| width: (parentNode.width || 0) + MoveRightDistance, | |||||
| position: { | |||||
| x: parentNode.position.x + MoveRightDistance / 2, | |||||
| y: parentNode.position.y, | |||||
| }, | |||||
| }); | |||||
| resizeIterationNode(type, params.position, node.parentId); | |||||
| } | } | ||||
| } | } | ||||
| data: { | data: { | ||||
| label: Operator.IterationStart, | label: Operator.IterationStart, | ||||
| name: Operator.IterationStart, | name: Operator.IterationStart, | ||||
| form: {}, | |||||
| form: initialIterationStartValues, | |||||
| }, | }, | ||||
| parentId: newNode.id, | parentId: newNode.id, | ||||
| extent: 'parent', | extent: 'parent', |
| return options; | return options; | ||||
| } | } | ||||
| export const useBuildVariableOptions = (nodeId?: string) => { | |||||
| export const useBuildVariableOptions = (nodeId?: string, parentId?: string) => { | |||||
| const nodeOutputOptions = useBuildNodeOutputOptions(nodeId); | const nodeOutputOptions = useBuildNodeOutputOptions(nodeId); | ||||
| const parentNodeOutputOptions = useBuildNodeOutputOptions(parentId); | |||||
| const beginOptions = useBuildBeginVariableOptions(); | const beginOptions = useBuildBeginVariableOptions(); | ||||
| const options = useMemo(() => { | const options = useMemo(() => { | ||||
| return [...beginOptions, ...nodeOutputOptions]; | |||||
| }, [beginOptions, nodeOutputOptions]); | |||||
| return [...beginOptions, ...nodeOutputOptions, ...parentNodeOutputOptions]; | |||||
| }, [beginOptions, nodeOutputOptions, parentNodeOutputOptions]); | |||||
| return options; | return options; | ||||
| }; | }; | ||||
| export function useBuildQueryVariableOptions() { | export function useBuildQueryVariableOptions() { | ||||
| const { data } = useFetchAgent(); | const { data } = useFetchAgent(); | ||||
| const node = useContext(AgentFormContext); | const node = useContext(AgentFormContext); | ||||
| const options = useBuildVariableOptions(node?.id); | |||||
| const options = useBuildVariableOptions(node?.id, node?.parentId); | |||||
| const nextOptions = useMemo(() => { | const nextOptions = useMemo(() => { | ||||
| const globals = data?.dsl?.globals ?? {}; | const globals = data?.dsl?.globals ?? {}; |
| export const initialIterationValues = { | export const initialIterationValues = { | ||||
| delimiter: ',', | delimiter: ',', | ||||
| }; | }; | ||||
| export const initialIterationStartValues = { | |||||
| outputs: { | |||||
| item: { | |||||
| type: 'unkown', | |||||
| }, | |||||
| index: { | |||||
| type: 'integer', | |||||
| }, | |||||
| }, | |||||
| }; | |||||
| export const initialIterationStartValues = {}; | |||||
| export const initialCodeValues = { | export const initialCodeValues = { | ||||
| lang: 'python', | lang: 'python', |