### What problem does this PR solve? Feat: Convert the inputs parameter of the begin operator #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality)tags/v0.19.1
| import { CodeTemplateStrMap, ProgrammingLanguage } from '@/constants/agent'; | import { CodeTemplateStrMap, ProgrammingLanguage } from '@/constants/agent'; | ||||
| export enum AgentDialogueMode { | export enum AgentDialogueMode { | ||||
| Conversational = 'Conversational', | |||||
| Task = 'Task', | |||||
| Conversational = 'conversational', | |||||
| Task = 'task', | |||||
| } | } | ||||
| import { | import { | ||||
| [Operator.IterationStart]: [Operator.Begin], | [Operator.IterationStart]: [Operator.Begin], | ||||
| [Operator.Code]: [Operator.Begin], | [Operator.Code]: [Operator.Begin], | ||||
| [Operator.WaitingDialogue]: [Operator.Begin], | [Operator.WaitingDialogue]: [Operator.Begin], | ||||
| [Operator.Agent]: [Operator.Begin], | |||||
| }; | }; | ||||
| export const NodeMap = { | export const NodeMap = { |
| import { buildSelectOptions } from '@/utils/component-util'; | import { buildSelectOptions } from '@/utils/component-util'; | ||||
| import { zodResolver } from '@hookform/resolvers/zod'; | import { zodResolver } from '@hookform/resolvers/zod'; | ||||
| import { Plus } from 'lucide-react'; | import { Plus } from 'lucide-react'; | ||||
| import { useCallback } from 'react'; | |||||
| import { useForm, useWatch } from 'react-hook-form'; | import { useForm, useWatch } from 'react-hook-form'; | ||||
| import { useTranslation } from 'react-i18next'; | import { useTranslation } from 'react-i18next'; | ||||
| import { z } from 'zod'; | import { z } from 'zod'; | ||||
| import { AgentDialogueMode } from '../../constant'; | import { AgentDialogueMode } from '../../constant'; | ||||
| import { useWatchFormChange } from '../../hooks/use-watch-form-change'; | |||||
| import { INextOperatorForm } from '../../interface'; | import { INextOperatorForm } from '../../interface'; | ||||
| import { ParameterDialog } from './parameter-dialog'; | import { ParameterDialog } from './parameter-dialog'; | ||||
| import { QueryTable } from './query-table'; | import { QueryTable } from './query-table'; | ||||
| import { useEditQueryRecord } from './use-edit-query'; | import { useEditQueryRecord } from './use-edit-query'; | ||||
| import { useValues } from './use-values'; | import { useValues } from './use-values'; | ||||
| import { useWatchFormChange } from './use-watch-change'; | |||||
| const ModeOptions = buildSelectOptions([ | const ModeOptions = buildSelectOptions([ | ||||
| AgentDialogueMode.Conversational, | AgentDialogueMode.Conversational, | ||||
| node, | node, | ||||
| }); | }); | ||||
| const handleParameterDialogSubmit = useCallback( | |||||
| (values: any) => { | |||||
| ok(values); | |||||
| }, | |||||
| [ok], | |||||
| ); | |||||
| return ( | return ( | ||||
| <section className="px-5 space-y-5"> | <section className="px-5 space-y-5"> | ||||
| <Form {...form}> | <Form {...form}> | ||||
| <ParameterDialog | <ParameterDialog | ||||
| hideModal={hideModal} | hideModal={hideModal} | ||||
| initialValue={currentRecord} | initialValue={currentRecord} | ||||
| onOk={ok} | |||||
| otherThanCurrentQuery={otherThanCurrentQuery} | otherThanCurrentQuery={otherThanCurrentQuery} | ||||
| submit={handleParameterDialogSubmit} | |||||
| submit={ok} | |||||
| ></ParameterDialog> | ></ParameterDialog> | ||||
| )} | )} | ||||
| </Form> | </Form> |
| import { useSetSelectedRecord } from '@/hooks/logic-hooks'; | import { useSetSelectedRecord } from '@/hooks/logic-hooks'; | ||||
| import { useCallback, useMemo, useState } from 'react'; | import { useCallback, useMemo, useState } from 'react'; | ||||
| import { BeginQuery, INextOperatorForm } from '../../interface'; | import { BeginQuery, INextOperatorForm } from '../../interface'; | ||||
| import useGraphStore from '../../store'; | |||||
| export function useUpdateQueryToNodeForm({ form, node }: INextOperatorForm) { | |||||
| const updateNodeForm = useGraphStore((state) => state.updateNodeForm); | |||||
| const update = useCallback( | |||||
| (inputs: BeginQuery[]) => { | |||||
| const values = form.getValues(); | |||||
| const nextValues = { ...values, inputs }; | |||||
| if (node?.id) { | |||||
| updateNodeForm(node.id, nextValues); | |||||
| } | |||||
| }, | |||||
| [form, node?.id, updateNodeForm], | |||||
| ); | |||||
| return { update }; | |||||
| } | |||||
| export const useEditQueryRecord = ({ form, node }: INextOperatorForm) => { | export const useEditQueryRecord = ({ form, node }: INextOperatorForm) => { | ||||
| const { setRecord, currentRecord } = useSetSelectedRecord<BeginQuery>(); | const { setRecord, currentRecord } = useSetSelectedRecord<BeginQuery>(); | ||||
| const { visible, hideModal, showModal } = useSetModalState(); | const { visible, hideModal, showModal } = useSetModalState(); | ||||
| const [index, setIndex] = useState(-1); | const [index, setIndex] = useState(-1); | ||||
| const { update } = useUpdateQueryToNodeForm({ form, node }); | |||||
| const otherThanCurrentQuery = useMemo(() => { | const otherThanCurrentQuery = useMemo(() => { | ||||
| const inputs: BeginQuery[] = form?.getValues('inputs') || []; | const inputs: BeginQuery[] = form?.getValues('inputs') || []; | ||||
| shouldTouch: true, | shouldTouch: true, | ||||
| }); | }); | ||||
| update(nextQuery); | |||||
| hideModal(); | hideModal(); | ||||
| }, | }, | ||||
| [form, hideModal, index, update], | |||||
| [form, hideModal, index], | |||||
| ); | ); | ||||
| const handleShowModal = useCallback( | const handleShowModal = useCallback( | ||||
| ); | ); | ||||
| form.setValue('inputs', nextQuery, { shouldDirty: true }); | form.setValue('inputs', nextQuery, { shouldDirty: true }); | ||||
| update(nextQuery); | |||||
| }, | }, | ||||
| [form, update], | |||||
| [form], | |||||
| ); | ); | ||||
| return { | return { |
| import { useMemo } from 'react'; | import { useMemo } from 'react'; | ||||
| import { useTranslation } from 'react-i18next'; | import { useTranslation } from 'react-i18next'; | ||||
| import { AgentDialogueMode } from '../../constant'; | import { AgentDialogueMode } from '../../constant'; | ||||
| import { BeginQuery } from '../../interface'; | |||||
| export function useValues(node?: RAGFlowNodeType) { | export function useValues(node?: RAGFlowNodeType) { | ||||
| const { t } = useTranslation(); | const { t } = useTranslation(); | ||||
| return defaultValues; | return defaultValues; | ||||
| } | } | ||||
| return formData; | |||||
| const inputs = Object.entries(formData?.inputs || {}).reduce<BeginQuery[]>( | |||||
| (pre, [key, value]) => { | |||||
| pre.push({ ...(value || {}), key }); | |||||
| return pre; | |||||
| }, | |||||
| [], | |||||
| ); | |||||
| return { ...(formData || {}), inputs }; | |||||
| }, [defaultValues, node?.data?.form]); | }, [defaultValues, node?.data?.form]); | ||||
| return values; | return values; |
| import { omit } from 'lodash'; | |||||
| import { useEffect } from 'react'; | |||||
| import { UseFormReturn, useWatch } from 'react-hook-form'; | |||||
| import { BeginQuery } from '../../interface'; | |||||
| import useGraphStore from '../../store'; | |||||
| function transferInputsArrayToObject(inputs: BeginQuery[] = []) { | |||||
| return inputs.reduce<Record<string, Omit<BeginQuery, 'key'>>>((pre, cur) => { | |||||
| pre[cur.key] = omit(cur, 'key'); | |||||
| return pre; | |||||
| }, {}); | |||||
| } | |||||
| export function useWatchFormChange(id?: string, form?: UseFormReturn) { | |||||
| let values = useWatch({ control: form?.control }); | |||||
| const updateNodeForm = useGraphStore((state) => state.updateNodeForm); | |||||
| useEffect(() => { | |||||
| if (id && form?.formState.isDirty) { | |||||
| values = form?.getValues(); | |||||
| const nextValues = { | |||||
| ...values, | |||||
| inputs: transferInputsArrayToObject(values.inputs), | |||||
| }; | |||||
| updateNodeForm(id, nextValues); | |||||
| } | |||||
| }, [form?.formState.isDirty, id, updateNodeForm, values]); | |||||
| } |