From 391c5586dd67b376e26bfe9a650865622b77a1fd Mon Sep 17 00:00:00 2001 From: balibabu Date: Wed, 30 Jul 2025 14:34:06 +0800 Subject: [PATCH] Feat: Add wencai operator #3221 (#9116) ### What problem does this PR solve? Feat: Add wencai operator #3221 ### Type of change - [x] New Feature (non-breaking change which adds functionality) --- .../node/dropdown/next-step-dropdown.tsx | 1 + web/src/pages/agent/constant.tsx | 8 +- .../agent-form/tool-popover/tool-command.tsx | 1 + .../pages/agent/form/tool-form/constant.tsx | 2 + .../form/tool-form/wencai-form/index.tsx | 35 +++++++ .../pages/agent/form/wencai-form/index.tsx | 96 +++++++++++++------ .../hooks/use-agent-tool-initial-values.ts | 2 + 7 files changed, 117 insertions(+), 28 deletions(-) create mode 100644 web/src/pages/agent/form/tool-form/wencai-form/index.tsx diff --git a/web/src/pages/agent/canvas/node/dropdown/next-step-dropdown.tsx b/web/src/pages/agent/canvas/node/dropdown/next-step-dropdown.tsx index 8356758d9..26589c170 100644 --- a/web/src/pages/agent/canvas/node/dropdown/next-step-dropdown.tsx +++ b/web/src/pages/agent/canvas/node/dropdown/next-step-dropdown.tsx @@ -112,6 +112,7 @@ function AccordionOperators() { Operator.PubMed, Operator.GitHub, Operator.Invoke, + Operator.WenCai, ]} > diff --git a/web/src/pages/agent/constant.tsx b/web/src/pages/agent/constant.tsx index eda0b81e0..c74ec2f0b 100644 --- a/web/src/pages/agent/constant.tsx +++ b/web/src/pages/agent/constant.tsx @@ -507,7 +507,13 @@ export const initialSwitchValues = { export const initialWenCaiValues = { top_n: 20, query_type: 'stock', - ...initialQueryBaseValues, + query: AgentGlobals.SysQuery, + outputs: { + report: { + value: '', + type: 'string', + }, + }, }; export const initialAkShareValues = { top_n: 10, ...initialQueryBaseValues }; diff --git a/web/src/pages/agent/form/agent-form/tool-popover/tool-command.tsx b/web/src/pages/agent/form/agent-form/tool-popover/tool-command.tsx index b724aacc2..8d86a007a 100644 --- a/web/src/pages/agent/form/agent-form/tool-popover/tool-command.tsx +++ b/web/src/pages/agent/form/agent-form/tool-popover/tool-command.tsx @@ -27,6 +27,7 @@ const Menus = [ Operator.PubMed, Operator.GoogleScholar, Operator.ArXiv, + Operator.WenCai, ], }, { diff --git a/web/src/pages/agent/form/tool-form/constant.tsx b/web/src/pages/agent/form/tool-form/constant.tsx index 3b7fb071f..1ae975533 100644 --- a/web/src/pages/agent/form/tool-form/constant.tsx +++ b/web/src/pages/agent/form/tool-form/constant.tsx @@ -13,6 +13,7 @@ import GoogleScholarForm from './google-scholar-form'; import PubMedForm from './pubmed-form'; import RetrievalForm from './retrieval-form'; import TavilyForm from './tavily-form'; +import WenCaiForm from './wencai-form'; import WikipediaForm from './wikipedia-form'; import YahooFinanceForm from './yahoo-finance-form'; @@ -35,4 +36,5 @@ export const ToolFormConfigMap = { [Operator.Email]: EmailForm, [Operator.TavilySearch]: TavilyForm, [Operator.TavilyExtract]: TavilyForm, + [Operator.WenCai]: WenCaiForm, }; diff --git a/web/src/pages/agent/form/tool-form/wencai-form/index.tsx b/web/src/pages/agent/form/tool-form/wencai-form/index.tsx new file mode 100644 index 000000000..38a8d923c --- /dev/null +++ b/web/src/pages/agent/form/tool-form/wencai-form/index.tsx @@ -0,0 +1,35 @@ +import { FormContainer } from '@/components/form-container'; +import { Form } from '@/components/ui/form'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { memo } from 'react'; +import { useForm } from 'react-hook-form'; +import { z } from 'zod'; +import { FormWrapper } from '../../components/form-wrapper'; +import { WenCaiFormWidgets, WenCaiPartialSchema } from '../../wencai-form'; +import { useValues } from '../use-values'; +import { useWatchFormChange } from '../use-watch-change'; + +function WenCaiForm() { + const values = useValues(); + + const FormSchema = z.object(WenCaiPartialSchema); + + const form = useForm>({ + defaultValues: values, + resolver: zodResolver(FormSchema), + }); + + useWatchFormChange(form); + + return ( +
+ + + + + +
+ ); +} + +export default memo(WenCaiForm); diff --git a/web/src/pages/agent/form/wencai-form/index.tsx b/web/src/pages/agent/form/wencai-form/index.tsx index 5297ee3d4..a4e668ed9 100644 --- a/web/src/pages/agent/form/wencai-form/index.tsx +++ b/web/src/pages/agent/form/wencai-form/index.tsx @@ -1,3 +1,4 @@ +import { FormContainer } from '@/components/form-container'; import { TopNFormField } from '@/components/top-n-item'; import { Form, @@ -8,14 +9,34 @@ import { FormMessage, } from '@/components/ui/form'; import { RAGFlowSelect } from '@/components/ui/select'; -import { useMemo } from 'react'; +import { zodResolver } from '@hookform/resolvers/zod'; +import { memo, useMemo } from 'react'; +import { useForm, useFormContext } from 'react-hook-form'; import { useTranslation } from 'react-i18next'; +import { z } from 'zod'; +import { initialWenCaiValues } from '../../constant'; +import { useFormValues } from '../../hooks/use-form-values'; +import { useWatchFormChange } from '../../hooks/use-watch-form-change'; import { INextOperatorForm } from '../../interface'; import { WenCaiQueryTypeOptions } from '../../options'; -import { DynamicInputVariable } from '../components/next-dynamic-input-variable'; +import { buildOutputList } from '../../utils/build-output-list'; +import { FormWrapper } from '../components/form-wrapper'; +import { Output } from '../components/output'; +import { QueryVariable } from '../components/query-variable'; -const WenCaiForm = ({ form, node }: INextOperatorForm) => { +export const WenCaiPartialSchema = { + top_n: z.number(), + query_type: z.string(), +}; + +export const FormSchema = z.object({ + ...WenCaiPartialSchema, + query: z.string(), +}); + +export function WenCaiFormWidgets() { const { t } = useTranslation(); + const form = useFormContext(); const wenCaiQueryTypeOptions = useMemo(() => { return WenCaiQueryTypeOptions.map((x) => ({ @@ -24,32 +45,53 @@ const WenCaiForm = ({ form, node }: INextOperatorForm) => { })); }, [t]); + return ( + <> + + ( + + {t('flow.queryType')} + + + + + + )} + /> + + ); +} + +const outputList = buildOutputList(initialWenCaiValues.outputs); + +function WenCaiForm({ node }: INextOperatorForm) { + const defaultValues = useFormValues(initialWenCaiValues, node); + + const form = useForm>({ + defaultValues, + resolver: zodResolver(FormSchema), + }); + + useWatchFormChange(node?.id, form); + return (
- { - e.preventDefault(); - }} - > - - - ( - - {t('flow.queryType')} - - - - - - )} - /> - + + + + + + + + +
+ +
); -}; +} -export default WenCaiForm; +export default memo(WenCaiForm); diff --git a/web/src/pages/agent/hooks/use-agent-tool-initial-values.ts b/web/src/pages/agent/hooks/use-agent-tool-initial-values.ts index b60aad44c..184079d5d 100644 --- a/web/src/pages/agent/hooks/use-agent-tool-initial-values.ts +++ b/web/src/pages/agent/hooks/use-agent-tool-initial-values.ts @@ -52,6 +52,8 @@ export function useAgentToolInitialValues() { return pick(initialValues, 'top_n', 'email'); case Operator.GitHub: return pick(initialValues, 'top_n'); + case Operator.WenCai: + return pick(initialValues, 'top_n', 'query_type'); default: return initialValues;