### What problem does this PR solve? feat: Add a note node to the agent canvas #2767 ### Type of change - [ ] Bug Fix (non-breaking change which fixes an issue) - [x] New Feature (non-breaking change which adds functionality) - [ ] Documentation Update - [ ] Refactoring - [ ] Performance Improvement - [ ] Other (please describe):tags/v0.13.0
| <svg t="1728464420455" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4344" | |||||
| width="200" height="200"> | |||||
| <path | |||||
| d="M864 64H704V32c0-17.066667-14.933333-32-32-32S640 14.933333 640 32V64H384V32c0-17.066667-14.933333-32-32-32S320 14.933333 320 32V64H160C142.933333 64 128 78.933333 128 96v896c0 17.066667 14.933333 32 32 32h704c17.066667 0 32-14.933333 32-32v-896c0-17.066667-14.933333-32-32-32zM832 960H192V128h128v64c0 17.066667 14.933333 32 32 32S384 209.066667 384 192V128h256v64c0 17.066667 14.933333 32 32 32S704 209.066667 704 192V128h128v832z" | |||||
| fill="#3b76f4" p-id="4345"></path> | |||||
| <path | |||||
| d="M704 384H320c-17.066667 0-32 14.933333-32 32S302.933333 448 320 448h384c17.066667 0 32-14.933333 32-32S721.066667 384 704 384zM704 640H320c-17.066667 0-32 14.933333-32 32S302.933333 704 320 704h384c17.066667 0 32-14.933333 32-32S721.066667 640 704 640z" | |||||
| fill="#3b76f4" p-id="4346"></path> | |||||
| </svg> |
| startDate: 'Start date', | startDate: 'Start date', | ||||
| endDate: 'End date', | endDate: 'End date', | ||||
| keyword: 'Keyword', | keyword: 'Keyword', | ||||
| note: 'Note', | |||||
| noteDescription: 'Note', | |||||
| notePlaceholder: 'Please enter a note', | |||||
| }, | }, | ||||
| footer: { | footer: { | ||||
| profile: 'All rights reserved @ React', | profile: 'All rights reserved @ React', |
| startDate: '開始日期', | startDate: '開始日期', | ||||
| endDate: '結束日期', | endDate: '結束日期', | ||||
| keyword: '關鍵字', | keyword: '關鍵字', | ||||
| note: '註解', | |||||
| noteDescription: '註解', | |||||
| notePlaceholder: '請輸入註釋', | |||||
| }, | }, | ||||
| footer: { | footer: { | ||||
| profile: '“保留所有權利 @ react”', | profile: '“保留所有權利 @ react”', |
| startDate: '开始日期', | startDate: '开始日期', | ||||
| endDate: '结束日期', | endDate: '结束日期', | ||||
| keyword: '关键字', | keyword: '关键字', | ||||
| note: '注释', | |||||
| noteDescription: '注释', | |||||
| notePlaceholder: '请输入注释', | |||||
| }, | }, | ||||
| footer: { | footer: { | ||||
| profile: 'All rights reserved @ React', | profile: 'All rights reserved @ React', |
| NodeMouseHandler, | NodeMouseHandler, | ||||
| } from 'reactflow'; | } from 'reactflow'; | ||||
| import 'reactflow/dist/style.css'; | import 'reactflow/dist/style.css'; | ||||
| import { ButtonEdge } from './edge'; | |||||
| import ChatDrawer from '../chat/drawer'; | |||||
| import { Operator } from '../constant'; | |||||
| import FlowDrawer from '../flow-drawer'; | import FlowDrawer from '../flow-drawer'; | ||||
| import { | import { | ||||
| useHandleDrop, | useHandleDrop, | ||||
| useValidateConnection, | useValidateConnection, | ||||
| useWatchNodeFormDataChange, | useWatchNodeFormDataChange, | ||||
| } from '../hooks'; | } from '../hooks'; | ||||
| import { RagNode } from './node'; | |||||
| import ChatDrawer from '../chat/drawer'; | |||||
| import { ButtonEdge } from './edge'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| import { RagNode } from './node'; | |||||
| import { BeginNode } from './node/begin-node'; | import { BeginNode } from './node/begin-node'; | ||||
| import { CategorizeNode } from './node/categorize-node'; | import { CategorizeNode } from './node/categorize-node'; | ||||
| import { LogicNode } from './node/logic-node'; | import { LogicNode } from './node/logic-node'; | ||||
| import NoteNode from './node/note-node'; | |||||
| import { RelevantNode } from './node/relevant-node'; | import { RelevantNode } from './node/relevant-node'; | ||||
| const nodeTypes = { | const nodeTypes = { | ||||
| beginNode: BeginNode, | beginNode: BeginNode, | ||||
| relevantNode: RelevantNode, | relevantNode: RelevantNode, | ||||
| logicNode: LogicNode, | logicNode: LogicNode, | ||||
| noteNode: NoteNode, | |||||
| }; | }; | ||||
| const edgeTypes = { | const edgeTypes = { | ||||
| const onNodeClick: NodeMouseHandler = useCallback( | const onNodeClick: NodeMouseHandler = useCallback( | ||||
| (e, node) => { | (e, node) => { | ||||
| showDrawer(node); | |||||
| if (node.data.label !== Operator.Note) { | |||||
| showDrawer(node); | |||||
| } | |||||
| }, | }, | ||||
| [showDrawer], | [showDrawer], | ||||
| ); | ); | ||||
| defaultEdgeOptions={{ | defaultEdgeOptions={{ | ||||
| type: 'buttonEdge', | type: 'buttonEdge', | ||||
| markerEnd: 'logo', | markerEnd: 'logo', | ||||
| // markerEnd: { | |||||
| // type: MarkerType.ArrowClosed, | |||||
| // color: 'rgb(157 149 225)', | |||||
| // width: 20, | |||||
| // height: 20, | |||||
| // }, | |||||
| style: { | style: { | ||||
| // edge style | |||||
| strokeWidth: 2, | strokeWidth: 2, | ||||
| stroke: 'rgb(202 197 245)', | stroke: 'rgb(202 197 245)', | ||||
| }, | }, |
| .ragNode { | |||||
| position: relative; | |||||
| .commonNode() { | |||||
| box-shadow: | box-shadow: | ||||
| -6px 0 12px 0 rgba(179, 177, 177, 0.08), | -6px 0 12px 0 rgba(179, 177, 177, 0.08), | ||||
| -3px 0 6px -4px rgba(0, 0, 0, 0.12), | -3px 0 6px -4px rgba(0, 0, 0, 0.12), | ||||
| -6px 0 16px 6px rgba(0, 0, 0, 0.05); | -6px 0 16px 6px rgba(0, 0, 0, 0.05); | ||||
| } | |||||
| .ragNode { | |||||
| position: relative; | |||||
| .commonNode(); | |||||
| padding: 5px; | padding: 5px; | ||||
| border-radius: 5px; | border-radius: 5px; | ||||
| .logicNode { | .logicNode { | ||||
| position: relative; | position: relative; | ||||
| box-shadow: | |||||
| -6px 0 12px 0 rgba(179, 177, 177, 0.08), | |||||
| -3px 0 6px -4px rgba(0, 0, 0, 0.12), | |||||
| -6px 0 16px 6px rgba(0, 0, 0, 0.05); | |||||
| .commonNode(); | |||||
| padding: 5px; | padding: 5px; | ||||
| border-radius: 5px; | border-radius: 5px; | ||||
| white-space: nowrap; | white-space: nowrap; | ||||
| } | } | ||||
| } | } | ||||
| .noteNode { | |||||
| .commonNode(); | |||||
| width: 140px; | |||||
| padding: 4px 6px 6px; | |||||
| border-radius: 10px; | |||||
| background-color: #dbf8f4; | |||||
| .noteTitle { | |||||
| font-size: 12px; | |||||
| } | |||||
| .noteForm { | |||||
| margin-top: 4px; | |||||
| } | |||||
| } |
| import { useTranslate } from '@/hooks/common-hooks'; | |||||
| import { Flex } from 'antd'; | import { Flex } from 'antd'; | ||||
| import classNames from 'classnames'; | import classNames from 'classnames'; | ||||
| import pick from 'lodash/pick'; | import pick from 'lodash/pick'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| import NodePopover from './popover'; | import NodePopover from './popover'; | ||||
| const ZeroGapOperators = [ | |||||
| Operator.RewriteQuestion, | |||||
| Operator.KeywordExtract, | |||||
| Operator.ArXiv, | |||||
| ]; | |||||
| export function RagNode({ | export function RagNode({ | ||||
| id, | id, | ||||
| data, | data, | ||||
| selected, | selected, | ||||
| }: NodeProps<NodeData>) { | }: NodeProps<NodeData>) { | ||||
| const style = operatorMap[data.label as Operator]; | const style = operatorMap[data.label as Operator]; | ||||
| const { t } = useTranslate('flow'); | |||||
| return ( | return ( | ||||
| <NodePopover nodeId={id}> | <NodePopover nodeId={id}> | ||||
| id="b" | id="b" | ||||
| ></Handle> | ></Handle> | ||||
| <Handle type="source" position={Position.Bottom} id="a" isConnectable /> | <Handle type="source" position={Position.Bottom} id="a" isConnectable /> | ||||
| <Flex | |||||
| vertical | |||||
| align="center" | |||||
| justify={'space-around'} | |||||
| // gap={ZeroGapOperators.some((x) => x === data.label) ? 0 : 6} | |||||
| > | |||||
| <Flex vertical align="center" justify={'space-around'}> | |||||
| <Flex flex={1} justify="center" align="center"> | <Flex flex={1} justify="center" align="center"> | ||||
| <label htmlFor=""> </label> | <label htmlFor=""> </label> | ||||
| </Flex> | </Flex> |
| import { Flex, Form, Input, Space } from 'antd'; | |||||
| import { NodeProps } from 'reactflow'; | |||||
| import { NodeData } from '../../interface'; | |||||
| import NodeDropdown from './dropdown'; | |||||
| import SvgIcon from '@/components/svg-icon'; | |||||
| import { useEffect } from 'react'; | |||||
| import { useTranslation } from 'react-i18next'; | |||||
| import { useHandleFormValuesChange } from '../../hooks'; | |||||
| import styles from './index.less'; | |||||
| const { TextArea } = Input; | |||||
| function NoteNode({ data, id }: NodeProps<NodeData>) { | |||||
| const { t } = useTranslation(); | |||||
| const [form] = Form.useForm(); | |||||
| const { handleValuesChange } = useHandleFormValuesChange(id); | |||||
| useEffect(() => { | |||||
| form.setFieldsValue(data?.form); | |||||
| }, [form, data?.form]); | |||||
| return ( | |||||
| <section className={styles.noteNode}> | |||||
| <Flex justify={'space-between'}> | |||||
| <Space size={'small'}> | |||||
| <SvgIcon name="note" width={14}></SvgIcon> | |||||
| <span className={styles.noteTitle}>{t('flow.note')}</span> | |||||
| </Space> | |||||
| <NodeDropdown id={id}></NodeDropdown> | |||||
| </Flex> | |||||
| <Form | |||||
| onValuesChange={handleValuesChange} | |||||
| form={form} | |||||
| className={styles.noteForm} | |||||
| > | |||||
| <Form.Item name="text" noStyle> | |||||
| <TextArea rows={3} placeholder={t('flow.notePlaceholder')} /> | |||||
| </Form.Item> | |||||
| </Form> | |||||
| </section> | |||||
| ); | |||||
| } | |||||
| export default NoteNode; |
| import { ReactComponent as GoogleIcon } from '@/assets/svg/google.svg'; | import { ReactComponent as GoogleIcon } from '@/assets/svg/google.svg'; | ||||
| import { ReactComponent as Jin10Icon } from '@/assets/svg/jin10.svg'; | import { ReactComponent as Jin10Icon } from '@/assets/svg/jin10.svg'; | ||||
| import { ReactComponent as KeywordIcon } from '@/assets/svg/keyword.svg'; | import { ReactComponent as KeywordIcon } from '@/assets/svg/keyword.svg'; | ||||
| import { ReactComponent as NoteIcon } from '@/assets/svg/note.svg'; | |||||
| import { ReactComponent as PubMedIcon } from '@/assets/svg/pubmed.svg'; | import { ReactComponent as PubMedIcon } from '@/assets/svg/pubmed.svg'; | ||||
| import { ReactComponent as QWeatherIcon } from '@/assets/svg/qweather.svg'; | import { ReactComponent as QWeatherIcon } from '@/assets/svg/qweather.svg'; | ||||
| import { ReactComponent as SwitchIcon } from '@/assets/svg/switch.svg'; | import { ReactComponent as SwitchIcon } from '@/assets/svg/switch.svg'; | ||||
| Jin10 = 'Jin10', | Jin10 = 'Jin10', | ||||
| Concentrator = 'Concentrator', | Concentrator = 'Concentrator', | ||||
| TuShare = 'TuShare', | TuShare = 'TuShare', | ||||
| Note = 'Note', | |||||
| } | } | ||||
| export const operatorIconMap = { | export const operatorIconMap = { | ||||
| [Operator.Jin10]: Jin10Icon, | [Operator.Jin10]: Jin10Icon, | ||||
| [Operator.Concentrator]: ConcentratorIcon, | [Operator.Concentrator]: ConcentratorIcon, | ||||
| [Operator.TuShare]: TuShareIcon, | [Operator.TuShare]: TuShareIcon, | ||||
| [Operator.Note]: NoteIcon, | |||||
| }; | }; | ||||
| export const operatorMap: Record< | export const operatorMap: Record< | ||||
| iconFontSize: 16, | iconFontSize: 16, | ||||
| }, | }, | ||||
| [Operator.TuShare]: { backgroundColor: '#f8cfa0' }, | [Operator.TuShare]: { backgroundColor: '#f8cfa0' }, | ||||
| [Operator.Note]: { backgroundColor: '#f8cfa0' }, | |||||
| }; | }; | ||||
| export const componentMenuList = [ | export const componentMenuList = [ | ||||
| { | { | ||||
| name: Operator.Concentrator, | name: Operator.Concentrator, | ||||
| }, | }, | ||||
| { | |||||
| name: Operator.Note, | |||||
| }, | |||||
| { | { | ||||
| name: Operator.DuckDuckGo, | name: Operator.DuckDuckGo, | ||||
| }, | }, | ||||
| start_date: '2024-01-01 09:00:00', | start_date: '2024-01-01 09:00:00', | ||||
| }; | }; | ||||
| export const initialNoteValues = { | |||||
| text: '', | |||||
| }; | |||||
| export const CategorizeAnchorPointPositions = [ | export const CategorizeAnchorPointPositions = [ | ||||
| { top: 1, right: 34 }, | { top: 1, right: 34 }, | ||||
| { top: 8, right: 18 }, | { top: 8, right: 18 }, | ||||
| [Operator.YahooFinance]: 'ragNode', | [Operator.YahooFinance]: 'ragNode', | ||||
| [Operator.Jin10]: 'ragNode', | [Operator.Jin10]: 'ragNode', | ||||
| [Operator.TuShare]: 'ragNode', | [Operator.TuShare]: 'ragNode', | ||||
| [Operator.Note]: 'noteNode', | |||||
| }; | }; | ||||
| export const LanguageOptions = [ | export const LanguageOptions = [ |
| import { Drawer, Flex, Form, Input } from 'antd'; | import { Drawer, Flex, Form, Input } from 'antd'; | ||||
| import { useEffect } from 'react'; | import { useEffect } from 'react'; | ||||
| import { Node } from 'reactflow'; | import { Node } from 'reactflow'; | ||||
| import AkShareForm from '../akshare-form'; | |||||
| import AnswerForm from '../answer-form'; | |||||
| import ArXivForm from '../arxiv-form'; | |||||
| import BaiduFanyiForm from '../baidu-fanyi-form'; | |||||
| import BaiduForm from '../baidu-form'; | |||||
| import BeginForm from '../begin-form'; | |||||
| import BingForm from '../bing-form'; | |||||
| import CategorizeForm from '../categorize-form'; | |||||
| import { Operator } from '../constant'; | import { Operator } from '../constant'; | ||||
| import DeepLForm from '../deepl-form'; | |||||
| import DuckDuckGoForm from '../duckduckgo-form'; | |||||
| import ExeSQLForm from '../exesql-form'; | |||||
| import GenerateForm from '../generate-form'; | |||||
| import GithubForm from '../github-form'; | |||||
| import GoogleForm from '../google-form'; | |||||
| import GoogleScholarForm from '../google-scholar-form'; | |||||
| import AkShareForm from '../form/akshare-form'; | |||||
| import AnswerForm from '../form/answer-form'; | |||||
| import ArXivForm from '../form/arxiv-form'; | |||||
| import BaiduFanyiForm from '../form/baidu-fanyi-form'; | |||||
| import BaiduForm from '../form/baidu-form'; | |||||
| import BeginForm from '../form/begin-form'; | |||||
| import BingForm from '../form/bing-form'; | |||||
| import CategorizeForm from '../form/categorize-form'; | |||||
| import DeepLForm from '../form/deepl-form'; | |||||
| import DuckDuckGoForm from '../form/duckduckgo-form'; | |||||
| import ExeSQLForm from '../form/exesql-form'; | |||||
| import GenerateForm from '../form/generate-form'; | |||||
| import GithubForm from '../form/github-form'; | |||||
| import GoogleForm from '../form/google-form'; | |||||
| import GoogleScholarForm from '../form/google-scholar-form'; | |||||
| import Jin10Form from '../form/jin10-form'; | |||||
| import KeywordExtractForm from '../form/keyword-extract-form'; | |||||
| import MessageForm from '../form/message-form'; | |||||
| import PubMedForm from '../form/pubmed-form'; | |||||
| import QWeatherForm from '../form/qweather-form'; | |||||
| import RelevantForm from '../form/relevant-form'; | |||||
| import RetrievalForm from '../form/retrieval-form'; | |||||
| import RewriteQuestionForm from '../form/rewrite-question-form'; | |||||
| import SwitchForm from '../form/switch-form'; | |||||
| import TuShareForm from '../form/tushare-form'; | |||||
| import WenCaiForm from '../form/wencai-form'; | |||||
| import WikipediaForm from '../form/wikipedia-form'; | |||||
| import YahooFinanceForm from '../form/yahoo-finance-form'; | |||||
| import { useHandleFormValuesChange, useHandleNodeNameChange } from '../hooks'; | import { useHandleFormValuesChange, useHandleNodeNameChange } from '../hooks'; | ||||
| import KeywordExtractForm from '../keyword-extract-form'; | |||||
| import MessageForm from '../message-form'; | |||||
| import OperatorIcon from '../operator-icon'; | import OperatorIcon from '../operator-icon'; | ||||
| import PubMedForm from '../pubmed-form'; | |||||
| import QWeatherForm from '../qweather-form'; | |||||
| import RelevantForm from '../relevant-form'; | |||||
| import RetrievalForm from '../retrieval-form'; | |||||
| import RewriteQuestionForm from '../rewrite-question-form'; | |||||
| import SwitchForm from '../switch-form'; | |||||
| import TuShareForm from '../tushare-form'; | |||||
| import WenCaiForm from '../wencai-form'; | |||||
| import WikipediaForm from '../wikipedia-form'; | |||||
| import Jin10Form from '../jin10-form'; | |||||
| import YahooFinanceForm from '../yahoo-finance-form'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| interface IProps { | interface IProps { |
| collapsed: boolean; | collapsed: boolean; | ||||
| } | } | ||||
| const dividerProps = { | |||||
| marginTop: 10, | |||||
| marginBottom: 10, | |||||
| padding: 0, | |||||
| borderBlockColor: '#b4afaf', | |||||
| borderStyle: 'dotted', | |||||
| }; | |||||
| const FlowSide = ({ setCollapsed, collapsed }: IProps) => { | const FlowSide = ({ setCollapsed, collapsed }: IProps) => { | ||||
| const { handleDragStart } = useHandleDrag(); | const { handleDragStart } = useHandleDrag(); | ||||
| const { t } = useTranslate('flow'); | const { t } = useTranslate('flow'); | ||||
| {componentMenuList.map((x) => { | {componentMenuList.map((x) => { | ||||
| return ( | return ( | ||||
| <React.Fragment key={x.name}> | <React.Fragment key={x.name}> | ||||
| {x.name === Operator.Note && ( | |||||
| <Divider style={dividerProps}></Divider> | |||||
| )} | |||||
| {x.name === Operator.DuckDuckGo && ( | {x.name === Operator.DuckDuckGo && ( | ||||
| <Divider | |||||
| style={{ | |||||
| marginTop: 10, | |||||
| marginBottom: 10, | |||||
| padding: 0, | |||||
| borderBlockColor: '#b4afaf', | |||||
| borderStyle: 'dotted', | |||||
| }} | |||||
| ></Divider> | |||||
| <Divider style={dividerProps}></Divider> | |||||
| )} | )} | ||||
| <Card | <Card | ||||
| key={x.name} | key={x.name} |
| import TopNItem from '@/components/top-n-item'; | import TopNItem from '@/components/top-n-item'; | ||||
| import { Form } from 'antd'; | import { Form } from 'antd'; | ||||
| import { IOperatorForm } from '../interface'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const AkShareForm = ({ onValuesChange, form }: IOperatorForm) => { | const AkShareForm = ({ onValuesChange, form }: IOperatorForm) => { | ||||
| return ( | return ( |
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { Form, Select } from 'antd'; | import { Form, Select } from 'antd'; | ||||
| import { useMemo } from 'react'; | import { useMemo } from 'react'; | ||||
| import { IOperatorForm } from '../interface'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const ArXivForm = ({ onValuesChange, form }: IOperatorForm) => { | const ArXivForm = ({ onValuesChange, form }: IOperatorForm) => { | ||||
| const { t } = useTranslate('flow'); | const { t } = useTranslate('flow'); |
| import { | import { | ||||
| BaiduFanyiDomainOptions, | BaiduFanyiDomainOptions, | ||||
| BaiduFanyiSourceLangOptions, | BaiduFanyiSourceLangOptions, | ||||
| } from '../constant'; | |||||
| import { IOperatorForm } from '../interface'; | |||||
| } from '../../constant'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const BaiduFanyiForm = ({ onValuesChange, form }: IOperatorForm) => { | const BaiduFanyiForm = ({ onValuesChange, form }: IOperatorForm) => { | ||||
| const { t } = useTranslate('flow'); | const { t } = useTranslate('flow'); |
| import TopNItem from '@/components/top-n-item'; | import TopNItem from '@/components/top-n-item'; | ||||
| import { Form } from 'antd'; | import { Form } from 'antd'; | ||||
| import { IOperatorForm } from '../interface'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const BaiduForm = ({ onValuesChange, form }: IOperatorForm) => { | const BaiduForm = ({ onValuesChange, form }: IOperatorForm) => { | ||||
| return ( | return ( |
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { Form, Input } from 'antd'; | import { Form, Input } from 'antd'; | ||||
| import { IOperatorForm } from '../interface'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| type FieldType = { | type FieldType = { | ||||
| prologue?: string; | prologue?: string; |
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { Form, Input, Select } from 'antd'; | import { Form, Input, Select } from 'antd'; | ||||
| import { useMemo } from 'react'; | import { useMemo } from 'react'; | ||||
| import { BingCountryOptions, BingLanguageOptions } from '../constant'; | |||||
| import { IOperatorForm } from '../interface'; | |||||
| import { BingCountryOptions, BingLanguageOptions } from '../../constant'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const BingForm = ({ onValuesChange, form }: IOperatorForm) => { | const BingForm = ({ onValuesChange, form }: IOperatorForm) => { | ||||
| const { t } = useTranslate('flow'); | const { t } = useTranslate('flow'); |
| useState, | useState, | ||||
| } from 'react'; | } from 'react'; | ||||
| import { useUpdateNodeInternals } from 'reactflow'; | import { useUpdateNodeInternals } from 'reactflow'; | ||||
| import { Operator } from '../constant'; | |||||
| import { useBuildFormSelectOptions } from '../form-hooks'; | |||||
| import { Operator } from '../../constant'; | |||||
| import { useBuildFormSelectOptions } from '../../form-hooks'; | |||||
| interface IProps { | interface IProps { | ||||
| nodeId?: string; | nodeId?: string; |
| ICategorizeItem, | ICategorizeItem, | ||||
| ICategorizeItemResult, | ICategorizeItemResult, | ||||
| IOperatorForm, | IOperatorForm, | ||||
| } from '../interface'; | |||||
| import useGraphStore from '../store'; | |||||
| } from '../../interface'; | |||||
| import useGraphStore from '../../store'; | |||||
| /** | /** | ||||
| * convert the following object into a list | * convert the following object into a list |
| import LLMSelect from '@/components/llm-select'; | import LLMSelect from '@/components/llm-select'; | ||||
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { Form } from 'antd'; | import { Form } from 'antd'; | ||||
| import { useSetLlmSetting } from '../hooks'; | |||||
| import { IOperatorForm } from '../interface'; | |||||
| import { useSetLlmSetting } from '../../hooks'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| import DynamicCategorize from './dynamic-categorize'; | import DynamicCategorize from './dynamic-categorize'; | ||||
| import { useHandleFormValuesChange } from './hooks'; | import { useHandleFormValuesChange } from './hooks'; | ||||
| import { Form } from 'antd'; | import { Form } from 'antd'; | ||||
| import { IOperatorForm } from '../interface'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const ConcentratorForm = ({ onValuesChange, form }: IOperatorForm) => { | const ConcentratorForm = ({ onValuesChange, form }: IOperatorForm) => { | ||||
| return ( | return ( |
| import TopNItem from '@/components/top-n-item'; | import TopNItem from '@/components/top-n-item'; | ||||
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { Form, Select } from 'antd'; | import { Form, Select } from 'antd'; | ||||
| import { DeepLSourceLangOptions, DeepLTargetLangOptions } from '../constant'; | |||||
| import { useBuildSortOptions } from '../form-hooks'; | |||||
| import { IOperatorForm } from '../interface'; | |||||
| import { DeepLSourceLangOptions, DeepLTargetLangOptions } from '../../constant'; | |||||
| import { useBuildSortOptions } from '../../form-hooks'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const DeepLForm = ({ onValuesChange, form }: IOperatorForm) => { | const DeepLForm = ({ onValuesChange, form }: IOperatorForm) => { | ||||
| const { t } = useTranslate('flow'); | const { t } = useTranslate('flow'); |
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { Form, Select } from 'antd'; | import { Form, Select } from 'antd'; | ||||
| import { useMemo } from 'react'; | import { useMemo } from 'react'; | ||||
| import { Channel } from '../constant'; | |||||
| import { IOperatorForm } from '../interface'; | |||||
| import { Channel } from '../../constant'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const DuckDuckGoForm = ({ onValuesChange, form }: IOperatorForm) => { | const DuckDuckGoForm = ({ onValuesChange, form }: IOperatorForm) => { | ||||
| const { t } = useTranslate('flow'); | const { t } = useTranslate('flow'); |
| import { useTestDbConnect } from '@/hooks/flow-hooks'; | import { useTestDbConnect } from '@/hooks/flow-hooks'; | ||||
| import { Button, Flex, Form, Input, InputNumber, Select } from 'antd'; | import { Button, Flex, Form, Input, InputNumber, Select } from 'antd'; | ||||
| import { useCallback } from 'react'; | import { useCallback } from 'react'; | ||||
| import { ExeSQLOptions } from '../constant'; | |||||
| import { IOperatorForm } from '../interface'; | |||||
| import { ExeSQLOptions } from '../../constant'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const ExeSQLForm = ({ onValuesChange, form }: IOperatorForm) => { | const ExeSQLForm = ({ onValuesChange, form }: IOperatorForm) => { | ||||
| const { t } = useTranslate('flow'); | const { t } = useTranslate('flow'); |
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { DeleteOutlined } from '@ant-design/icons'; | import { DeleteOutlined } from '@ant-design/icons'; | ||||
| import { Button, Flex, Select, Table, TableProps } from 'antd'; | import { Button, Flex, Select, Table, TableProps } from 'antd'; | ||||
| import { IGenerateParameter } from '../interface'; | |||||
| import { IGenerateParameter } from '../../interface'; | |||||
| import { useBuildComponentIdSelectOptions } from '../hooks'; | |||||
| import { useBuildComponentIdSelectOptions } from '../../hooks'; | |||||
| import { useHandleOperateParameters } from './hooks'; | import { useHandleOperateParameters } from './hooks'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| import get from 'lodash/get'; | import get from 'lodash/get'; | ||||
| import { useCallback, useMemo } from 'react'; | import { useCallback, useMemo } from 'react'; | ||||
| import { v4 as uuid } from 'uuid'; | import { v4 as uuid } from 'uuid'; | ||||
| import { IGenerateParameter } from '../interface'; | |||||
| import useGraphStore from '../store'; | |||||
| import { IGenerateParameter } from '../../interface'; | |||||
| import useGraphStore from '../../store'; | |||||
| export const useHandleOperateParameters = (nodeId: string) => { | export const useHandleOperateParameters = (nodeId: string) => { | ||||
| const { getNode, updateNodeForm } = useGraphStore((state) => state); | const { getNode, updateNodeForm } = useGraphStore((state) => state); |
| import LLMSelect from '@/components/llm-select'; | import LLMSelect from '@/components/llm-select'; | ||||
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { Form, Input, InputNumber, Switch } from 'antd'; | import { Form, Input, InputNumber, Switch } from 'antd'; | ||||
| import { useSetLlmSetting } from '../hooks'; | |||||
| import { IOperatorForm } from '../interface'; | |||||
| import { useSetLlmSetting } from '../../hooks'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| import DynamicParameters from './dynamic-parameters'; | import DynamicParameters from './dynamic-parameters'; | ||||
| const GenerateForm = ({ onValuesChange, form, node }: IOperatorForm) => { | const GenerateForm = ({ onValuesChange, form, node }: IOperatorForm) => { |
| import TopNItem from '@/components/top-n-item'; | import TopNItem from '@/components/top-n-item'; | ||||
| import { Form } from 'antd'; | import { Form } from 'antd'; | ||||
| import { IOperatorForm } from '../interface'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const GithubForm = ({ onValuesChange, form }: IOperatorForm) => { | const GithubForm = ({ onValuesChange, form }: IOperatorForm) => { | ||||
| return ( | return ( |
| import TopNItem from '@/components/top-n-item'; | import TopNItem from '@/components/top-n-item'; | ||||
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { Form, Input, Select } from 'antd'; | import { Form, Input, Select } from 'antd'; | ||||
| import { GoogleCountryOptions, GoogleLanguageOptions } from '../constant'; | |||||
| import { IOperatorForm } from '../interface'; | |||||
| import { GoogleCountryOptions, GoogleLanguageOptions } from '../../constant'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const GoogleForm = ({ onValuesChange, form }: IOperatorForm) => { | const GoogleForm = ({ onValuesChange, form }: IOperatorForm) => { | ||||
| const { t } = useTranslate('flow'); | const { t } = useTranslate('flow'); |
| import { DatePicker, DatePickerProps, Form, Select, Switch } from 'antd'; | import { DatePicker, DatePickerProps, Form, Select, Switch } from 'antd'; | ||||
| import dayjs from 'dayjs'; | import dayjs from 'dayjs'; | ||||
| import { useCallback, useMemo } from 'react'; | import { useCallback, useMemo } from 'react'; | ||||
| import { useBuildSortOptions } from '../form-hooks'; | |||||
| import { IOperatorForm } from '../interface'; | |||||
| import { useBuildSortOptions } from '../../form-hooks'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const YearPicker = ({ | const YearPicker = ({ | ||||
| onChange, | onChange, |
| Jin10SymbolsDatatypeOptions, | Jin10SymbolsDatatypeOptions, | ||||
| Jin10SymbolsTypeOptions, | Jin10SymbolsTypeOptions, | ||||
| Jin10TypeOptions, | Jin10TypeOptions, | ||||
| } from '../constant'; | |||||
| import { IOperatorForm } from '../interface'; | |||||
| } from '../../constant'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const Jin10Form = ({ onValuesChange, form }: IOperatorForm) => { | const Jin10Form = ({ onValuesChange, form }: IOperatorForm) => { | ||||
| const { t } = useTranslate('flow'); | const { t } = useTranslate('flow'); |
| import TopNItem from '@/components/top-n-item'; | import TopNItem from '@/components/top-n-item'; | ||||
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { Form } from 'antd'; | import { Form } from 'antd'; | ||||
| import { useSetLlmSetting } from '../hooks'; | |||||
| import { IOperatorForm } from '../interface'; | |||||
| import { useSetLlmSetting } from '../../hooks'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const KeywordExtractForm = ({ onValuesChange, form }: IOperatorForm) => { | const KeywordExtractForm = ({ onValuesChange, form }: IOperatorForm) => { | ||||
| const { t } = useTranslate('flow'); | const { t } = useTranslate('flow'); |
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; | import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons'; | ||||
| import { Button, Form, Input } from 'antd'; | import { Button, Form, Input } from 'antd'; | ||||
| import { IOperatorForm } from '../interface'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| import TopNItem from '@/components/top-n-item'; | import TopNItem from '@/components/top-n-item'; | ||||
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { Form, Input } from 'antd'; | import { Form, Input } from 'antd'; | ||||
| import { IOperatorForm } from '../interface'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const PubMedForm = ({ onValuesChange, form }: IOperatorForm) => { | const PubMedForm = ({ onValuesChange, form }: IOperatorForm) => { | ||||
| const { t } = useTranslate('flow'); | const { t } = useTranslate('flow'); |
| QWeatherTimePeriodOptions, | QWeatherTimePeriodOptions, | ||||
| QWeatherTypeOptions, | QWeatherTypeOptions, | ||||
| QWeatherUserTypeOptions, | QWeatherUserTypeOptions, | ||||
| } from '../constant'; | |||||
| import { IOperatorForm } from '../interface'; | |||||
| } from '../../constant'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const QWeatherForm = ({ onValuesChange, form }: IOperatorForm) => { | const QWeatherForm = ({ onValuesChange, form }: IOperatorForm) => { | ||||
| const { t } = useTranslate('flow'); | const { t } = useTranslate('flow'); |
| import pick from 'lodash/pick'; | import pick from 'lodash/pick'; | ||||
| import { useCallback, useEffect } from 'react'; | import { useCallback, useEffect } from 'react'; | ||||
| import { Edge } from 'reactflow'; | import { Edge } from 'reactflow'; | ||||
| import { IOperatorForm } from '../interface'; | |||||
| import useGraphStore from '../store'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| import useGraphStore from '../../store'; | |||||
| export const useBuildRelevantOptions = () => { | export const useBuildRelevantOptions = () => { | ||||
| const nodes = useGraphStore((state) => state.nodes); | const nodes = useGraphStore((state) => state.nodes); |
| import LLMSelect from '@/components/llm-select'; | import LLMSelect from '@/components/llm-select'; | ||||
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { Form, Select } from 'antd'; | import { Form, Select } from 'antd'; | ||||
| import { Operator } from '../constant'; | |||||
| import { useBuildFormSelectOptions } from '../form-hooks'; | |||||
| import { useSetLlmSetting } from '../hooks'; | |||||
| import { IOperatorForm } from '../interface'; | |||||
| import { Operator } from '../../constant'; | |||||
| import { useBuildFormSelectOptions } from '../../form-hooks'; | |||||
| import { useSetLlmSetting } from '../../hooks'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| import { useWatchConnectionChanges } from './hooks'; | import { useWatchConnectionChanges } from './hooks'; | ||||
| const RelevantForm = ({ onValuesChange, form, node }: IOperatorForm) => { | const RelevantForm = ({ onValuesChange, form, node }: IOperatorForm) => { |
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import type { FormProps } from 'antd'; | import type { FormProps } from 'antd'; | ||||
| import { Form, Input } from 'antd'; | import { Form, Input } from 'antd'; | ||||
| import { IOperatorForm } from '../interface'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| type FieldType = { | type FieldType = { | ||||
| top_n?: number; | top_n?: number; |
| import LLMSelect from '@/components/llm-select'; | import LLMSelect from '@/components/llm-select'; | ||||
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { Form, InputNumber } from 'antd'; | import { Form, InputNumber } from 'antd'; | ||||
| import { useSetLlmSetting } from '../hooks'; | |||||
| import { IOperatorForm } from '../interface'; | |||||
| import { useSetLlmSetting } from '../../hooks'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const RewriteQuestionForm = ({ onValuesChange, form }: IOperatorForm) => { | const RewriteQuestionForm = ({ onValuesChange, form }: IOperatorForm) => { | ||||
| const { t } = useTranslate('chat'); | const { t } = useTranslate('chat'); |
| SwitchElseTo, | SwitchElseTo, | ||||
| SwitchLogicOperatorOptions, | SwitchLogicOperatorOptions, | ||||
| SwitchOperatorOptions, | SwitchOperatorOptions, | ||||
| } from '../constant'; | |||||
| import { useBuildFormSelectOptions } from '../form-hooks'; | |||||
| import { useBuildComponentIdSelectOptions } from '../hooks'; | |||||
| import { IOperatorForm, ISwitchForm } from '../interface'; | |||||
| import { getOtherFieldValues } from '../utils'; | |||||
| } from '../../constant'; | |||||
| import { useBuildFormSelectOptions } from '../../form-hooks'; | |||||
| import { useBuildComponentIdSelectOptions } from '../../hooks'; | |||||
| import { IOperatorForm, ISwitchForm } from '../../interface'; | |||||
| import { getOtherFieldValues } from '../../utils'; | |||||
| const subLabelCol = { | const subLabelCol = { | ||||
| span: 11, | span: 11, |
| import { DatePicker, DatePickerProps, Form, Input, Select } from 'antd'; | import { DatePicker, DatePickerProps, Form, Input, Select } from 'antd'; | ||||
| import dayjs from 'dayjs'; | import dayjs from 'dayjs'; | ||||
| import { useCallback, useMemo } from 'react'; | import { useCallback, useMemo } from 'react'; | ||||
| import { TuShareSrcOptions } from '../constant'; | |||||
| import { IOperatorForm } from '../interface'; | |||||
| import { TuShareSrcOptions } from '../../constant'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const DateTimePicker = ({ | const DateTimePicker = ({ | ||||
| onChange, | onChange, |
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { Form, Select } from 'antd'; | import { Form, Select } from 'antd'; | ||||
| import { useMemo } from 'react'; | import { useMemo } from 'react'; | ||||
| import { WenCaiQueryTypeOptions } from '../constant'; | |||||
| import { IOperatorForm } from '../interface'; | |||||
| import { WenCaiQueryTypeOptions } from '../../constant'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const WenCaiForm = ({ onValuesChange, form }: IOperatorForm) => { | const WenCaiForm = ({ onValuesChange, form }: IOperatorForm) => { | ||||
| const { t } = useTranslate('flow'); | const { t } = useTranslate('flow'); |
| import TopNItem from '@/components/top-n-item'; | import TopNItem from '@/components/top-n-item'; | ||||
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { Form, Select } from 'antd'; | import { Form, Select } from 'antd'; | ||||
| import { LanguageOptions } from '../constant'; | |||||
| import { IOperatorForm } from '../interface'; | |||||
| import { LanguageOptions } from '../../constant'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const WikipediaForm = ({ onValuesChange, form }: IOperatorForm) => { | const WikipediaForm = ({ onValuesChange, form }: IOperatorForm) => { | ||||
| const { t } = useTranslate('common'); | const { t } = useTranslate('common'); |
| import { useTranslate } from '@/hooks/common-hooks'; | import { useTranslate } from '@/hooks/common-hooks'; | ||||
| import { Form, Switch } from 'antd'; | import { Form, Switch } from 'antd'; | ||||
| import { IOperatorForm } from '../interface'; | |||||
| import { IOperatorForm } from '../../interface'; | |||||
| const YahooFinanceForm = ({ onValuesChange, form }: IOperatorForm) => { | const YahooFinanceForm = ({ onValuesChange, form }: IOperatorForm) => { | ||||
| const { t } = useTranslate('flow'); | const { t } = useTranslate('flow'); |
| initialJin10Values, | initialJin10Values, | ||||
| initialKeywordExtractValues, | initialKeywordExtractValues, | ||||
| initialMessageValues, | initialMessageValues, | ||||
| initialNoteValues, | |||||
| initialPubMedValues, | initialPubMedValues, | ||||
| initialQWeatherValues, | initialQWeatherValues, | ||||
| initialRelevantValues, | initialRelevantValues, | ||||
| [Operator.Jin10]: initialJin10Values, | [Operator.Jin10]: initialJin10Values, | ||||
| [Operator.Concentrator]: initialConcentratorValues, | [Operator.Concentrator]: initialConcentratorValues, | ||||
| [Operator.TuShare]: initialTuShareValues, | [Operator.TuShare]: initialTuShareValues, | ||||
| [Operator.Note]: initialNoteValues, | |||||
| }; | }; | ||||
| }, [llmId]); | }, [llmId]); | ||||
| ): DSLComponents => { | ): DSLComponents => { | ||||
| const components: DSLComponents = {}; | const components: DSLComponents = {}; | ||||
| nodes.forEach((x) => { | |||||
| const id = x.id; | |||||
| const operatorName = x.data.label; | |||||
| components[id] = { | |||||
| obj: { | |||||
| component_name: operatorName, | |||||
| params: | |||||
| buildOperatorParams(operatorName)( | |||||
| x.data.form as Record<string, unknown>, | |||||
| ) ?? {}, | |||||
| }, | |||||
| downstream: buildComponentDownstreamOrUpstream(edges, id, true), | |||||
| upstream: buildComponentDownstreamOrUpstream(edges, id, false), | |||||
| }; | |||||
| }); | |||||
| nodes | |||||
| .filter((x) => x.data.label !== Operator.Note) | |||||
| .forEach((x) => { | |||||
| const id = x.id; | |||||
| const operatorName = x.data.label; | |||||
| components[id] = { | |||||
| obj: { | |||||
| component_name: operatorName, | |||||
| params: | |||||
| buildOperatorParams(operatorName)( | |||||
| x.data.form as Record<string, unknown>, | |||||
| ) ?? {}, | |||||
| }, | |||||
| downstream: buildComponentDownstreamOrUpstream(edges, id, true), | |||||
| upstream: buildComponentDownstreamOrUpstream(edges, id, false), | |||||
| }; | |||||
| }); | |||||
| return components; | return components; | ||||
| }; | }; |