Feat: The agent's external page should be able to fill in the begin parameter after being reset in task mode #9745 (#9982)

### What problem does this PR solve?

Feat: The agent's external page should be able to fill in the begin
parameter after being reset in task mode #9745

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu
2025-09-08 18:59:51 +08:00
committed by GitHub
parent e8018fde83
commit 2616f651c9
14 changed files with 234 additions and 880 deletions

View File

@ -1523,7 +1523,7 @@ This delimiter is used to split the input text into several text pieces echo of
sqlStatement: 'SQL Statement', sqlStatement: 'SQL Statement',
sqlStatementTip: sqlStatementTip:
'Write your SQL query here. You can use variables, raw SQL, or mix both using variable syntax.', 'Write your SQL query here. You can use variables, raw SQL, or mix both using variable syntax.',
frameworkPrompts: 'Framework Prompts', frameworkPrompts: 'Framework',
}, },
llmTools: { llmTools: {
bad_calculator: { bad_calculator: {

View File

@ -1436,7 +1436,7 @@ General实体和关系提取提示来自 GitHub - microsoft/graphrag基于
sqlStatement: 'SQL 语句', sqlStatement: 'SQL 语句',
sqlStatementTip: sqlStatementTip:
'在此处编写您的 SQL 查询。您可以使用变量、原始 SQL或使用变量语法混合使用两者。', '在此处编写您的 SQL 查询。您可以使用变量、原始 SQL或使用变量语法混合使用两者。',
frameworkPrompts: '框架提示词', frameworkPrompts: '框架',
}, },
footer: { footer: {
profile: 'All rights reserved @ React', profile: 'All rights reserved @ React',

View File

@ -1,13 +1,16 @@
import { SharedFrom } from '@/constants/chat'; import { SharedFrom } from '@/constants/chat';
import { useSetModalState } from '@/hooks/common-hooks'; import { useSetModalState } from '@/hooks/common-hooks';
import { useFetchExternalAgentInputs } from '@/hooks/use-agent-request';
import { IEventList } from '@/hooks/use-send-message'; import { IEventList } from '@/hooks/use-send-message';
import { import {
buildRequestBody, buildRequestBody,
useSendAgentMessage, useSendAgentMessage,
} from '@/pages/agent/chat/use-send-agent-message'; } from '@/pages/agent/chat/use-send-agent-message';
import { isEmpty } from 'lodash';
import trim from 'lodash/trim'; import trim from 'lodash/trim';
import { useCallback, useState } from 'react'; import { useCallback, useEffect, useRef, useState } from 'react';
import { useSearchParams } from 'umi'; import { useSearchParams } from 'umi';
import { AgentDialogueMode } from '../constant';
export const useSendButtonDisabled = (value: string) => { export const useSendButtonDisabled = (value: string) => {
return trim(value) === ''; return trim(value) === '';
@ -35,12 +38,15 @@ export const useGetSharedChatSearchParams = () => {
export const useSendNextSharedMessage = ( export const useSendNextSharedMessage = (
addEventList: (data: IEventList, messageId: string) => void, addEventList: (data: IEventList, messageId: string) => void,
isTaskMode: boolean,
) => { ) => {
const { from, sharedId: conversationId } = useGetSharedChatSearchParams(); const { from, sharedId: conversationId } = useGetSharedChatSearchParams();
const url = `/api/v1/${from === SharedFrom.Agent ? 'agentbots' : 'chatbots'}/${conversationId}/completions`; const url = `/api/v1/${from === SharedFrom.Agent ? 'agentbots' : 'chatbots'}/${conversationId}/completions`;
const { data: inputsData } = useFetchExternalAgentInputs();
const [params, setParams] = useState<any[]>([]); const [params, setParams] = useState<any[]>([]);
const sendedTaskMessage = useRef<boolean>(false);
const isTaskMode = inputsData.mode === AgentDialogueMode.Task;
const { const {
visible: parameterDialogVisible, visible: parameterDialogVisible,
@ -73,10 +79,27 @@ export const useSendNextSharedMessage = (
[hideParameterDialog, isTaskMode, ret], [hideParameterDialog, isTaskMode, ret],
); );
const runTask = useCallback(() => {
if (
isTaskMode &&
isEmpty(inputsData?.inputs) &&
!sendedTaskMessage.current
) {
ok([]);
sendedTaskMessage.current = true;
}
}, [inputsData?.inputs, isTaskMode, ok]);
useEffect(() => {
runTask();
}, [runTask]);
return { return {
...ret, ...ret,
hasError: false, hasError: false,
parameterDialogVisible, parameterDialogVisible,
inputsData,
isTaskMode,
hideParameterDialog, hideParameterDialog,
showParameterDialog, showParameterDialog,
ok, ok,

View File

@ -5,10 +5,7 @@ import MessageItem from '@/components/next-message-item';
import PdfDrawer from '@/components/pdf-drawer'; import PdfDrawer from '@/components/pdf-drawer';
import { useClickDrawer } from '@/components/pdf-drawer/hooks'; import { useClickDrawer } from '@/components/pdf-drawer/hooks';
import { MessageType } from '@/constants/chat'; import { MessageType } from '@/constants/chat';
import { import { useUploadCanvasFileWithProgress } from '@/hooks/use-agent-request';
useFetchExternalAgentInputs,
useUploadCanvasFileWithProgress,
} from '@/hooks/use-agent-request';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import i18n from '@/locales/config'; import i18n from '@/locales/config';
import DebugContent from '@/pages/agent/debug-content'; import DebugContent from '@/pages/agent/debug-content';
@ -18,7 +15,6 @@ import { useSendButtonDisabled } from '@/pages/chat/hooks';
import { buildMessageUuidWithRole } from '@/utils/chat'; import { buildMessageUuidWithRole } from '@/utils/chat';
import { isEmpty } from 'lodash'; import { isEmpty } from 'lodash';
import React, { forwardRef, useCallback } from 'react'; import React, { forwardRef, useCallback } from 'react';
import { AgentDialogueMode } from '../constant';
import { import {
useGetSharedChatSearchParams, useGetSharedChatSearchParams,
useSendNextSharedMessage, useSendNextSharedMessage,
@ -43,9 +39,6 @@ const ChatContainer = () => {
clearEventList, clearEventList,
} = useCacheChatLog(); } = useCacheChatLog();
const { data: inputsData } = useFetchExternalAgentInputs();
const isTaskMode = inputsData.mode === AgentDialogueMode.Task;
const { const {
handlePressEnter, handlePressEnter,
handleInputChange, handleInputChange,
@ -55,6 +48,8 @@ const ChatContainer = () => {
messageContainerRef, messageContainerRef,
derivedMessages, derivedMessages,
hasError, hasError,
inputsData,
isTaskMode,
stopOutputMessage, stopOutputMessage,
findReferenceByMessageId, findReferenceByMessageId,
appendUploadResponseList, appendUploadResponseList,
@ -64,7 +59,8 @@ const ChatContainer = () => {
addNewestOneAnswer, addNewestOneAnswer,
ok, ok,
resetSession, resetSession,
} = useSendNextSharedMessage(addEventList, isTaskMode); } = useSendNextSharedMessage(addEventList);
const { buildInputList, handleOk, isWaitting } = useAwaitCompentData({ const { buildInputList, handleOk, isWaitting } = useAwaitCompentData({
derivedMessages, derivedMessages,
sendFormMessage, sendFormMessage,
@ -72,6 +68,12 @@ const ChatContainer = () => {
}); });
const sendDisabled = useSendButtonDisabled(value); const sendDisabled = useSendButtonDisabled(value);
const showBeginParameterDialog = useCallback(() => {
if (inputsData && inputsData.inputs && !isEmpty(inputsData.inputs)) {
showParameterDialog();
}
}, [inputsData, showParameterDialog]);
const handleUploadFile: NonNullable<FileUploadProps['onUpload']> = const handleUploadFile: NonNullable<FileUploadProps['onUpload']> =
useCallback( useCallback(
async (files, options) => { async (files, options) => {
@ -96,10 +98,8 @@ const ChatContainer = () => {
}, [inputsData.prologue, addNewestOneAnswer, isTaskMode]); }, [inputsData.prologue, addNewestOneAnswer, isTaskMode]);
React.useEffect(() => { React.useEffect(() => {
if (inputsData && inputsData.inputs && !isEmpty(inputsData.inputs)) { showBeginParameterDialog();
showParameterDialog(); }, [showBeginParameterDialog]);
}
}, [inputsData, showParameterDialog]);
const handleInputsModalOk = (params: any[]) => { const handleInputsModalOk = (params: any[]) => {
ok(params); ok(params);
@ -107,10 +107,14 @@ const ChatContainer = () => {
const handleReset = () => { const handleReset = () => {
resetSession(); resetSession();
clearEventList(); clearEventList();
if (isTaskMode) {
showBeginParameterDialog();
}
}; };
if (!conversationId) { if (!conversationId) {
return <div>empty</div>; return <div>empty</div>;
} }
return ( return (
<> <>
<EmbedContainer <EmbedContainer

View File

@ -18,7 +18,7 @@ import {
} from '@xyflow/react'; } from '@xyflow/react';
import '@xyflow/react/dist/style.css'; import '@xyflow/react/dist/style.css';
import { NotebookPen } from 'lucide-react'; import { NotebookPen } from 'lucide-react';
import { useCallback, useRef, useState } from 'react'; import { memo, useCallback, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { AgentBackground } from '../components/background'; import { AgentBackground } from '../components/background';
import { AgentInstanceContext, HandleContext } from '../context'; import { AgentInstanceContext, HandleContext } from '../context';
@ -41,6 +41,7 @@ import { RagNode } from './node';
import { AgentNode } from './node/agent-node'; import { AgentNode } from './node/agent-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 ChunkerNode from './node/chunker-node';
import { InnerNextStepDropdown } from './node/dropdown/next-step-dropdown'; import { InnerNextStepDropdown } from './node/dropdown/next-step-dropdown';
import { GenerateNode } from './node/generate-node'; import { GenerateNode } from './node/generate-node';
import { InvokeNode } from './node/invoke-node'; import { InvokeNode } from './node/invoke-node';
@ -49,11 +50,13 @@ import { KeywordNode } from './node/keyword-node';
import { LogicNode } from './node/logic-node'; import { LogicNode } from './node/logic-node';
import { MessageNode } from './node/message-node'; import { MessageNode } from './node/message-node';
import NoteNode from './node/note-node'; import NoteNode from './node/note-node';
import ParserNode from './node/parser-node';
import { RelevantNode } from './node/relevant-node'; import { RelevantNode } from './node/relevant-node';
import { RetrievalNode } from './node/retrieval-node'; import { RetrievalNode } from './node/retrieval-node';
import { RewriteNode } from './node/rewrite-node'; import { RewriteNode } from './node/rewrite-node';
import { SwitchNode } from './node/switch-node'; import { SwitchNode } from './node/switch-node';
import { TemplateNode } from './node/template-node'; import { TemplateNode } from './node/template-node';
import TokenizerNode from './node/tokenizer-node';
import { ToolNode } from './node/tool-node'; import { ToolNode } from './node/tool-node';
export const nodeTypes: NodeTypes = { export const nodeTypes: NodeTypes = {
@ -76,6 +79,9 @@ export const nodeTypes: NodeTypes = {
iterationStartNode: IterationStartNode, iterationStartNode: IterationStartNode,
agentNode: AgentNode, agentNode: AgentNode,
toolNode: ToolNode, toolNode: ToolNode,
parserNode: ParserNode,
chunkerNode: ChunkerNode,
tokenizerNode: TokenizerNode,
}; };
const edgeTypes = { const edgeTypes = {
@ -87,7 +93,7 @@ interface IProps {
hideDrawer(): void; hideDrawer(): void;
} }
function AgentCanvas({ drawerVisible, hideDrawer }: IProps) { function DataFlowCanvas({ drawerVisible, hideDrawer }: IProps) {
const { t } = useTranslation(); const { t } = useTranslation();
const { const {
nodes, nodes,
@ -323,4 +329,4 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) {
); );
} }
export default AgentCanvas; export default memo(DataFlowCanvas);

View File

@ -0,0 +1,49 @@
import { IRagNode } from '@/interfaces/database/flow';
import { NodeProps, Position } from '@xyflow/react';
import { memo } from 'react';
import { NodeHandleId } from '../../constant';
import { needsSingleStepDebugging } from '../../utils';
import { CommonHandle } from './handle';
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
import NodeHeader from './node-header';
import { NodeWrapper } from './node-wrapper';
import { ToolBar } from './toolbar';
function ChunkerNode({
id,
data,
isConnectable = true,
selected,
}: NodeProps<IRagNode>) {
return (
<ToolBar
selected={selected}
id={id}
label={data.label}
showRun={needsSingleStepDebugging(data.label)}
>
<NodeWrapper selected={selected}>
<CommonHandle
id={NodeHandleId.End}
type="target"
position={Position.Left}
isConnectable={isConnectable}
style={LeftHandleStyle}
nodeId={id}
></CommonHandle>
<CommonHandle
type="source"
position={Position.Right}
isConnectable={isConnectable}
id={NodeHandleId.Start}
style={RightHandleStyle}
nodeId={id}
isConnectableEnd={false}
></CommonHandle>
<NodeHeader id={id} name={data.name} label={data.label}></NodeHeader>
</NodeWrapper>
</ToolBar>
);
}
export default memo(ChunkerNode);

View File

@ -0,0 +1,49 @@
import { IRagNode } from '@/interfaces/database/flow';
import { NodeProps, Position } from '@xyflow/react';
import { memo } from 'react';
import { NodeHandleId } from '../../constant';
import { needsSingleStepDebugging } from '../../utils';
import { CommonHandle } from './handle';
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
import NodeHeader from './node-header';
import { NodeWrapper } from './node-wrapper';
import { ToolBar } from './toolbar';
function ParserNode({
id,
data,
isConnectable = true,
selected,
}: NodeProps<IRagNode>) {
return (
<ToolBar
selected={selected}
id={id}
label={data.label}
showRun={needsSingleStepDebugging(data.label)}
>
<NodeWrapper selected={selected}>
<CommonHandle
id={NodeHandleId.End}
type="target"
position={Position.Left}
isConnectable={isConnectable}
style={LeftHandleStyle}
nodeId={id}
></CommonHandle>
<CommonHandle
type="source"
position={Position.Right}
isConnectable={isConnectable}
id={NodeHandleId.Start}
style={RightHandleStyle}
nodeId={id}
isConnectableEnd={false}
></CommonHandle>
<NodeHeader id={id} name={data.name} label={data.label}></NodeHeader>
</NodeWrapper>
</ToolBar>
);
}
export default memo(ParserNode);

View File

@ -0,0 +1,49 @@
import { IRagNode } from '@/interfaces/database/flow';
import { NodeProps, Position } from '@xyflow/react';
import { memo } from 'react';
import { NodeHandleId } from '../../constant';
import { needsSingleStepDebugging } from '../../utils';
import { CommonHandle } from './handle';
import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
import NodeHeader from './node-header';
import { NodeWrapper } from './node-wrapper';
import { ToolBar } from './toolbar';
function TokenizerNode({
id,
data,
isConnectable = true,
selected,
}: NodeProps<IRagNode>) {
return (
<ToolBar
selected={selected}
id={id}
label={data.label}
showRun={needsSingleStepDebugging(data.label)}
>
<NodeWrapper selected={selected}>
<CommonHandle
id={NodeHandleId.End}
type="target"
position={Position.Left}
isConnectable={isConnectable}
style={LeftHandleStyle}
nodeId={id}
></CommonHandle>
<CommonHandle
type="source"
position={Position.Right}
isConnectable={isConnectable}
id={NodeHandleId.Start}
style={RightHandleStyle}
nodeId={id}
isConnectableEnd={false}
></CommonHandle>
<NodeHeader id={id} name={data.name} label={data.label}></NodeHeader>
</NodeWrapper>
</ToolBar>
);
}
export default memo(TokenizerNode);

View File

@ -8,11 +8,6 @@ import {
ProgrammingLanguage, ProgrammingLanguage,
} from '@/constants/agent'; } from '@/constants/agent';
export enum AgentDialogueMode {
Conversational = 'conversational',
Task = 'task',
}
import { import {
ChatVariableEnabledField, ChatVariableEnabledField,
variableEnabledFieldMap, variableEnabledFieldMap,
@ -22,17 +17,6 @@ import i18n from '@/locales/config';
import { setInitialChatVariableEnabledFieldValue } from '@/utils/chat'; import { setInitialChatVariableEnabledFieldValue } from '@/utils/chat';
import { t } from 'i18next'; import { t } from 'i18next';
// DuckDuckGo's channel options
export enum Channel {
Text = 'text',
News = 'news',
}
export enum PromptRole {
User = 'user',
Assistant = 'assistant',
}
import { import {
Circle, Circle,
CircleSlash2, CircleSlash2,
@ -44,6 +28,16 @@ import {
WrapText, WrapText,
} from 'lucide-react'; } from 'lucide-react';
export enum PromptRole {
User = 'user',
Assistant = 'assistant',
}
export enum AgentDialogueMode {
Conversational = 'conversational',
Task = 'task',
}
export const BeginId = 'begin'; export const BeginId = 'begin';
export enum Operator { export enum Operator {
@ -54,26 +48,9 @@ export enum Operator {
Relevant = 'Relevant', Relevant = 'Relevant',
RewriteQuestion = 'RewriteQuestion', RewriteQuestion = 'RewriteQuestion',
KeywordExtract = 'KeywordExtract', KeywordExtract = 'KeywordExtract',
Baidu = 'Baidu',
DuckDuckGo = 'DuckDuckGo',
Wikipedia = 'Wikipedia',
PubMed = 'PubMed',
ArXiv = 'ArXiv',
Google = 'Google',
Bing = 'Bing',
GoogleScholar = 'GoogleScholar',
DeepL = 'DeepL',
GitHub = 'GitHub',
BaiduFanyi = 'BaiduFanyi',
QWeather = 'QWeather',
ExeSQL = 'ExeSQL', ExeSQL = 'ExeSQL',
Switch = 'Switch', Switch = 'Switch',
WenCai = 'WenCai',
AkShare = 'AkShare',
YahooFinance = 'YahooFinance',
Jin10 = 'Jin10',
Concentrator = 'Concentrator', Concentrator = 'Concentrator',
TuShare = 'TuShare',
Note = 'Note', Note = 'Note',
Crawler = 'Crawler', Crawler = 'Crawler',
Invoke = 'Invoke', Invoke = 'Invoke',
@ -84,11 +61,8 @@ export enum Operator {
WaitingDialogue = 'WaitingDialogue', WaitingDialogue = 'WaitingDialogue',
Agent = 'Agent', Agent = 'Agent',
Tool = 'Tool', Tool = 'Tool',
TavilySearch = 'TavilySearch',
TavilyExtract = 'TavilyExtract',
UserFillUp = 'UserFillUp', UserFillUp = 'UserFillUp',
StringTransform = 'StringTransform', StringTransform = 'StringTransform',
SearXNG = 'SearXNG',
Parser = 'Parser', Parser = 'Parser',
Chunker = 'Chunker', Chunker = 'Chunker',
Tokenizer = 'Tokenizer', Tokenizer = 'Tokenizer',
@ -114,112 +88,6 @@ export const AgentOperatorList = [
Operator.Agent, Operator.Agent,
]; ];
export const componentMenuList = [
{
name: Operator.Retrieval,
},
{
name: Operator.Categorize,
},
{
name: Operator.Message,
},
{
name: Operator.RewriteQuestion,
},
{
name: Operator.KeywordExtract,
},
{
name: Operator.Switch,
},
{
name: Operator.Concentrator,
},
{
name: Operator.Iteration,
},
{
name: Operator.Code,
},
{
name: Operator.WaitingDialogue,
},
{
name: Operator.Agent,
},
{
name: Operator.Note,
},
{
name: Operator.DuckDuckGo,
},
{
name: Operator.Baidu,
},
{
name: Operator.Wikipedia,
},
{
name: Operator.PubMed,
},
{
name: Operator.ArXiv,
},
{
name: Operator.Google,
},
{
name: Operator.Bing,
},
{
name: Operator.GoogleScholar,
},
{
name: Operator.DeepL,
},
{
name: Operator.GitHub,
},
{
name: Operator.BaiduFanyi,
},
{
name: Operator.QWeather,
},
{
name: Operator.ExeSQL,
},
{
name: Operator.WenCai,
},
{
name: Operator.AkShare,
},
{
name: Operator.YahooFinance,
},
{
name: Operator.Jin10,
},
{
name: Operator.TuShare,
},
{
name: Operator.Crawler,
},
{
name: Operator.Invoke,
},
{
name: Operator.Email,
},
{
name: Operator.SearXNG,
},
];
export const SwitchOperatorOptions = [ export const SwitchOperatorOptions = [
{ value: '=', label: 'equal', icon: 'equal' }, { value: '=', label: 'equal', icon: 'equal' },
{ value: '≠', label: 'notEqual', icon: 'not-equals' }, { value: '≠', label: 'notEqual', icon: 'not-equals' },
@ -331,161 +199,6 @@ export const initialKeywordExtractValues = {
top_n: 3, top_n: 3,
...initialQueryBaseValues, ...initialQueryBaseValues,
}; };
export const initialDuckValues = {
top_n: 10,
channel: Channel.Text,
query: AgentGlobals.SysQuery,
outputs: {
formalized_content: {
value: '',
type: 'string',
},
json: {
value: [],
type: 'Array<Object>',
},
},
};
export const initialSearXNGValues = {
top_n: '10',
searxng_url: '',
query: AgentGlobals.SysQuery,
outputs: {
formalized_content: {
value: '',
type: 'string',
},
json: {
value: [],
type: 'Array<Object>',
},
},
};
export const initialBaiduValues = {
top_n: 10,
...initialQueryBaseValues,
};
export const initialWikipediaValues = {
top_n: 10,
language: 'en',
query: AgentGlobals.SysQuery,
outputs: {
formalized_content: {
value: '',
type: 'string',
},
},
};
export const initialPubMedValues = {
top_n: 12,
email: '',
query: AgentGlobals.SysQuery,
outputs: {
formalized_content: {
value: '',
type: 'string',
},
},
};
export const initialArXivValues = {
top_n: 12,
sort_by: 'relevance',
query: AgentGlobals.SysQuery,
outputs: {
formalized_content: {
value: '',
type: 'string',
},
},
};
export const initialGoogleValues = {
q: AgentGlobals.SysQuery,
start: 0,
num: 12,
api_key: '',
country: 'us',
language: 'en',
outputs: {
formalized_content: {
value: '',
type: 'string',
},
json: {
value: [],
type: 'Array<Object>',
},
},
};
export const initialBingValues = {
top_n: 10,
channel: 'Webpages',
api_key:
'YOUR_API_KEY (obtained from https://www.microsoft.com/en-us/bing/apis/bing-web-search-api)',
country: 'CH',
language: 'en',
query: '',
};
export const initialGoogleScholarValues = {
top_n: 12,
sort_by: 'relevance',
patents: true,
query: AgentGlobals.SysQuery,
year_low: undefined,
year_high: undefined,
outputs: {
formalized_content: {
value: '',
type: 'string',
},
json: {
value: [],
type: 'Array<Object>',
},
},
};
export const initialDeepLValues = {
top_n: 5,
auth_key: 'relevance',
};
export const initialGithubValues = {
top_n: 5,
query: AgentGlobals.SysQuery,
outputs: {
formalized_content: {
value: '',
type: 'string',
},
json: {
value: [],
type: 'Array<Object>',
},
},
};
export const initialBaiduFanyiValues = {
appid: 'xxx',
secret_key: 'xxx',
trans_type: 'translate',
...initialQueryBaseValues,
};
export const initialQWeatherValues = {
web_apikey: 'xxx',
type: 'weather',
user_type: 'free',
time_period: 'now',
...initialQueryBaseValues,
};
export const initialExeSqlValues = { export const initialExeSqlValues = {
sql: '', sql: '',
@ -523,54 +236,8 @@ export const initialSwitchValues = {
[SwitchElseTo]: [], [SwitchElseTo]: [],
}; };
export const initialWenCaiValues = {
top_n: 20,
query_type: 'stock',
query: AgentGlobals.SysQuery,
outputs: {
report: {
value: '',
type: 'string',
},
},
};
export const initialAkShareValues = { top_n: 10, ...initialQueryBaseValues };
export const initialYahooFinanceValues = {
stock_code: '',
info: true,
history: false,
financials: false,
balance_sheet: false,
cash_flow_statement: false,
news: true,
outputs: {
report: {
value: '',
type: 'string',
},
},
};
export const initialJin10Values = {
type: 'flash',
secret_key: 'xxx',
flash_type: '1',
contain: '',
filter: '',
...initialQueryBaseValues,
};
export const initialConcentratorValues = {}; export const initialConcentratorValues = {};
export const initialTuShareValues = {
token: 'xxx',
src: 'eastmoney',
start_date: '2024-01-01 09:00:00',
...initialQueryBaseValues,
};
export const initialNoteValues = { export const initialNoteValues = {
text: '', text: '',
}; };
@ -650,6 +317,10 @@ export const initialCodeValues = {
export const initialWaitingDialogueValues = {}; export const initialWaitingDialogueValues = {};
export const initialChunkerValues = {};
export const initialTokenizerValues = {};
export const initialAgentValues = { export const initialAgentValues = {
...initialLlmBaseValues, ...initialLlmBaseValues,
description: '', description: '',
@ -717,66 +388,7 @@ export const initialStringTransformValues = {
}, },
}; };
export enum TavilySearchDepth { export const initialParserValues = {};
Basic = 'basic',
Advanced = 'advanced',
}
export enum TavilyTopic {
News = 'news',
General = 'general',
}
export const initialTavilyValues = {
api_key: '',
query: AgentGlobals.SysQuery,
search_depth: TavilySearchDepth.Basic,
topic: TavilyTopic.General,
max_results: 5,
days: 7,
include_answer: false,
include_raw_content: true,
include_images: false,
include_image_descriptions: false,
include_domains: [],
exclude_domains: [],
outputs: {
formalized_content: {
value: '',
type: 'string',
},
json: {
value: [],
type: 'Array<Object>',
},
},
};
export enum TavilyExtractDepth {
Basic = 'basic',
Advanced = 'advanced',
}
export enum TavilyExtractFormat {
Text = 'text',
Markdown = 'markdown',
}
export const initialTavilyExtractValues = {
urls: '',
extract_depth: TavilyExtractDepth.Basic,
format: TavilyExtractFormat.Markdown,
outputs: {
formalized_content: {
value: '',
type: 'string',
},
json: {
value: [],
type: 'Array<Object>',
},
},
};
export const CategorizeAnchorPointPositions = [ export const CategorizeAnchorPointPositions = [
{ top: 1, right: 34 }, { top: 1, right: 34 },
@ -818,27 +430,9 @@ export const RestrictedUpstreamMap = {
Operator.Message, Operator.Message,
Operator.Relevant, Operator.Relevant,
], ],
[Operator.Baidu]: [Operator.Begin, Operator.Retrieval],
[Operator.DuckDuckGo]: [Operator.Begin, Operator.Retrieval],
[Operator.Wikipedia]: [Operator.Begin, Operator.Retrieval],
[Operator.PubMed]: [Operator.Begin, Operator.Retrieval],
[Operator.ArXiv]: [Operator.Begin, Operator.Retrieval],
[Operator.Google]: [Operator.Begin, Operator.Retrieval],
[Operator.Bing]: [Operator.Begin, Operator.Retrieval],
[Operator.GoogleScholar]: [Operator.Begin, Operator.Retrieval],
[Operator.DeepL]: [Operator.Begin, Operator.Retrieval],
[Operator.GitHub]: [Operator.Begin, Operator.Retrieval],
[Operator.BaiduFanyi]: [Operator.Begin, Operator.Retrieval],
[Operator.QWeather]: [Operator.Begin, Operator.Retrieval],
[Operator.SearXNG]: [Operator.Begin, Operator.Retrieval],
[Operator.ExeSQL]: [Operator.Begin], [Operator.ExeSQL]: [Operator.Begin],
[Operator.Switch]: [Operator.Begin], [Operator.Switch]: [Operator.Begin],
[Operator.WenCai]: [Operator.Begin],
[Operator.AkShare]: [Operator.Begin],
[Operator.YahooFinance]: [Operator.Begin],
[Operator.Jin10]: [Operator.Begin],
[Operator.Concentrator]: [Operator.Begin], [Operator.Concentrator]: [Operator.Begin],
[Operator.TuShare]: [Operator.Begin],
[Operator.Crawler]: [Operator.Begin], [Operator.Crawler]: [Operator.Begin],
[Operator.Note]: [], [Operator.Note]: [],
[Operator.Invoke]: [Operator.Begin], [Operator.Invoke]: [Operator.Begin],
@ -848,8 +442,6 @@ export const RestrictedUpstreamMap = {
[Operator.Code]: [Operator.Begin], [Operator.Code]: [Operator.Begin],
[Operator.WaitingDialogue]: [Operator.Begin], [Operator.WaitingDialogue]: [Operator.Begin],
[Operator.Agent]: [Operator.Begin], [Operator.Agent]: [Operator.Begin],
[Operator.TavilySearch]: [Operator.Begin],
[Operator.TavilyExtract]: [Operator.Begin],
[Operator.StringTransform]: [Operator.Begin], [Operator.StringTransform]: [Operator.Begin],
[Operator.UserFillUp]: [Operator.Begin], [Operator.UserFillUp]: [Operator.Begin],
[Operator.Tool]: [Operator.Begin], [Operator.Tool]: [Operator.Begin],
@ -863,27 +455,9 @@ export const NodeMap = {
[Operator.Relevant]: 'relevantNode', [Operator.Relevant]: 'relevantNode',
[Operator.RewriteQuestion]: 'rewriteNode', [Operator.RewriteQuestion]: 'rewriteNode',
[Operator.KeywordExtract]: 'keywordNode', [Operator.KeywordExtract]: 'keywordNode',
[Operator.DuckDuckGo]: 'ragNode',
[Operator.Baidu]: 'ragNode',
[Operator.Wikipedia]: 'ragNode',
[Operator.PubMed]: 'ragNode',
[Operator.ArXiv]: 'ragNode',
[Operator.Google]: 'ragNode',
[Operator.Bing]: 'ragNode',
[Operator.GoogleScholar]: 'ragNode',
[Operator.DeepL]: 'ragNode',
[Operator.GitHub]: 'ragNode',
[Operator.BaiduFanyi]: 'ragNode',
[Operator.QWeather]: 'ragNode',
[Operator.SearXNG]: 'ragNode',
[Operator.ExeSQL]: 'ragNode', [Operator.ExeSQL]: 'ragNode',
[Operator.Switch]: 'switchNode', [Operator.Switch]: 'switchNode',
[Operator.Concentrator]: 'logicNode', [Operator.Concentrator]: 'logicNode',
[Operator.WenCai]: 'ragNode',
[Operator.AkShare]: 'ragNode',
[Operator.YahooFinance]: 'ragNode',
[Operator.Jin10]: 'ragNode',
[Operator.TuShare]: 'ragNode',
[Operator.Note]: 'noteNode', [Operator.Note]: 'noteNode',
[Operator.Crawler]: 'ragNode', [Operator.Crawler]: 'ragNode',
[Operator.Invoke]: 'ragNode', [Operator.Invoke]: 'ragNode',
@ -894,10 +468,11 @@ export const NodeMap = {
[Operator.WaitingDialogue]: 'ragNode', [Operator.WaitingDialogue]: 'ragNode',
[Operator.Agent]: 'agentNode', [Operator.Agent]: 'agentNode',
[Operator.Tool]: 'toolNode', [Operator.Tool]: 'toolNode',
[Operator.TavilySearch]: 'ragNode',
[Operator.UserFillUp]: 'ragNode', [Operator.UserFillUp]: 'ragNode',
[Operator.StringTransform]: 'ragNode', [Operator.StringTransform]: 'ragNode',
[Operator.TavilyExtract]: 'ragNode', [Operator.Parser]: 'parserNode',
[Operator.Chunker]: 'chunkerNode',
[Operator.Tokenizer]: 'tokenizerNode',
}; };
export enum BeginQueryType { export enum BeginQueryType {

View File

@ -1,69 +1,12 @@
import { import { Connection, Edge, getOutgoers } from '@xyflow/react';
Connection, import { useCallback } from 'react';
Edge,
getOutgoers,
Node,
Position,
ReactFlowInstance,
} from '@xyflow/react';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
// import { shallow } from 'zustand/shallow'; // import { shallow } from 'zustand/shallow';
import { useFetchModelId } from '@/hooks/logic-hooks';
import { RAGFlowNodeType } from '@/interfaces/database/flow'; import { RAGFlowNodeType } from '@/interfaces/database/flow';
import { humanId } from 'human-id'; import { lowerFirst } from 'lodash';
import { get, lowerFirst } from 'lodash';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { import { Operator, RestrictedUpstreamMap } from './constant';
initialAgentValues,
initialAkShareValues,
initialArXivValues,
initialBaiduFanyiValues,
initialBeginValues,
initialBingValues,
initialCategorizeValues,
initialCodeValues,
initialConcentratorValues,
initialCrawlerValues,
initialDeepLValues,
initialDuckValues,
initialEmailValues,
initialExeSqlValues,
initialGithubValues,
initialGoogleScholarValues,
initialGoogleValues,
initialInvokeValues,
initialIterationValues,
initialJin10Values,
initialKeywordExtractValues,
initialMessageValues,
initialNoteValues,
initialPubMedValues,
initialQWeatherValues,
initialRelevantValues,
initialRetrievalValues,
initialRewriteQuestionValues,
initialSearXNGValues,
initialStringTransformValues,
initialSwitchValues,
initialTavilyExtractValues,
initialTavilyValues,
initialTuShareValues,
initialUserFillUpValues,
initialWaitingDialogueValues,
initialWenCaiValues,
initialWikipediaValues,
initialYahooFinanceValues,
NodeMap,
Operator,
RestrictedUpstreamMap,
} from './constant';
import useGraphStore, { RFState } from './store'; import useGraphStore, { RFState } from './store';
import { import { replaceIdWithText } from './utils';
generateNodeNamesWithIncreasingIndex,
getNodeDragHandle,
getRelativePositionToIterationNode,
replaceIdWithText,
} from './utils';
const selector = (state: RFState) => ({ const selector = (state: RFState) => ({
nodes: state.nodes, nodes: state.nodes,
@ -83,83 +26,6 @@ export const useSelectCanvasData = () => {
return useGraphStore(selector); return useGraphStore(selector);
}; };
export const useInitializeOperatorParams = () => {
const llmId = useFetchModelId();
const initialFormValuesMap = useMemo(() => {
return {
[Operator.Begin]: initialBeginValues,
[Operator.Retrieval]: initialRetrievalValues,
[Operator.Categorize]: { ...initialCategorizeValues, llm_id: llmId },
[Operator.Relevant]: { ...initialRelevantValues, llm_id: llmId },
[Operator.RewriteQuestion]: {
...initialRewriteQuestionValues,
llm_id: llmId,
},
[Operator.Message]: initialMessageValues,
[Operator.KeywordExtract]: {
...initialKeywordExtractValues,
llm_id: llmId,
},
[Operator.DuckDuckGo]: initialDuckValues,
[Operator.Wikipedia]: initialWikipediaValues,
[Operator.PubMed]: initialPubMedValues,
[Operator.ArXiv]: initialArXivValues,
[Operator.Google]: initialGoogleValues,
[Operator.Bing]: initialBingValues,
[Operator.GoogleScholar]: initialGoogleScholarValues,
[Operator.DeepL]: initialDeepLValues,
[Operator.SearXNG]: initialSearXNGValues,
[Operator.GitHub]: initialGithubValues,
[Operator.BaiduFanyi]: initialBaiduFanyiValues,
[Operator.QWeather]: initialQWeatherValues,
[Operator.ExeSQL]: { ...initialExeSqlValues, llm_id: llmId },
[Operator.Switch]: initialSwitchValues,
[Operator.WenCai]: initialWenCaiValues,
[Operator.AkShare]: initialAkShareValues,
[Operator.YahooFinance]: initialYahooFinanceValues,
[Operator.Jin10]: initialJin10Values,
[Operator.Concentrator]: initialConcentratorValues,
[Operator.TuShare]: initialTuShareValues,
[Operator.Note]: initialNoteValues,
[Operator.Crawler]: initialCrawlerValues,
[Operator.Invoke]: initialInvokeValues,
[Operator.Email]: initialEmailValues,
[Operator.Iteration]: initialIterationValues,
[Operator.IterationStart]: initialIterationValues,
[Operator.Code]: initialCodeValues,
[Operator.WaitingDialogue]: initialWaitingDialogueValues,
[Operator.Agent]: { ...initialAgentValues, llm_id: llmId },
[Operator.TavilySearch]: initialTavilyValues,
[Operator.TavilyExtract]: initialTavilyExtractValues,
[Operator.Tool]: {},
[Operator.UserFillUp]: initialUserFillUpValues,
[Operator.StringTransform]: initialStringTransformValues,
};
}, [llmId]);
const initializeOperatorParams = useCallback(
(operatorName: Operator) => {
return initialFormValuesMap[operatorName];
},
[initialFormValuesMap],
);
return initializeOperatorParams;
};
export const useHandleDrag = () => {
const handleDragStart = useCallback(
(operatorId: string) => (ev: React.DragEvent<HTMLDivElement>) => {
ev.dataTransfer.setData('application/@xyflow/react', operatorId);
ev.dataTransfer.effectAllowed = 'move';
},
[],
);
return { handleDragStart };
};
export const useGetNodeName = () => { export const useGetNodeName = () => {
const { t } = useTranslation(); const { t } = useTranslation();
@ -169,91 +35,6 @@ export const useGetNodeName = () => {
}; };
}; };
export const useHandleDrop = () => {
const addNode = useGraphStore((state) => state.addNode);
const nodes = useGraphStore((state) => state.nodes);
const [reactFlowInstance, setReactFlowInstance] =
useState<ReactFlowInstance<any, any>>();
const initializeOperatorParams = useInitializeOperatorParams();
const getNodeName = useGetNodeName();
const onDragOver = useCallback((event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
event.dataTransfer.dropEffect = 'move';
}, []);
const onDrop = useCallback(
(event: React.DragEvent<HTMLDivElement>) => {
event.preventDefault();
const type = event.dataTransfer.getData('application/@xyflow/react');
// check if the dropped element is valid
if (typeof type === 'undefined' || !type) {
return;
}
// reactFlowInstance.project was renamed to reactFlowInstance.screenToFlowPosition
// and you don't need to subtract the reactFlowBounds.left/top anymore
// details: https://@xyflow/react.dev/whats-new/2023-11-10
const position = reactFlowInstance?.screenToFlowPosition({
x: event.clientX,
y: event.clientY,
});
const newNode: Node<any> = {
id: `${type}:${humanId()}`,
type: NodeMap[type as Operator] || 'ragNode',
position: position || {
x: 0,
y: 0,
},
data: {
label: `${type}`,
name: generateNodeNamesWithIncreasingIndex(getNodeName(type), nodes),
form: initializeOperatorParams(type as Operator),
},
sourcePosition: Position.Right,
targetPosition: Position.Left,
dragHandle: getNodeDragHandle(type),
};
if (type === Operator.Iteration) {
newNode.width = 500;
newNode.height = 250;
const iterationStartNode: Node<any> = {
id: `${Operator.IterationStart}:${humanId()}`,
type: 'iterationStartNode',
position: { x: 50, y: 100 },
// draggable: false,
data: {
label: Operator.IterationStart,
name: Operator.IterationStart,
form: {},
},
parentId: newNode.id,
extent: 'parent',
};
addNode(newNode);
addNode(iterationStartNode);
} else {
const subNodeOfIteration = getRelativePositionToIterationNode(
nodes,
position,
);
if (subNodeOfIteration) {
newNode.parentId = subNodeOfIteration.parentId;
newNode.position = subNodeOfIteration.position;
newNode.extent = 'parent';
}
addNode(newNode);
}
},
[reactFlowInstance, getNodeName, nodes, initializeOperatorParams, addNode],
);
return { onDrop, onDragOver, setReactFlowInstance, reactFlowInstance };
};
export const useValidateConnection = () => { export const useValidateConnection = () => {
const { getOperatorTypeFromId, getParentIdById, edges, nodes } = const { getOperatorTypeFromId, getParentIdById, edges, nodes } =
useGraphStore((state) => state); useGraphStore((state) => state);
@ -352,52 +133,3 @@ export const useDuplicateNode = () => {
return duplicateNode; return duplicateNode;
}; };
export const useCopyPaste = () => {
const nodes = useGraphStore((state) => state.nodes);
const duplicateNode = useDuplicateNode();
const onCopyCapture = useCallback(
(event: ClipboardEvent) => {
if (get(event, 'srcElement.tagName') !== 'BODY') return;
event.preventDefault();
const nodesStr = JSON.stringify(
nodes.filter((n) => n.selected && n.data.label !== Operator.Begin),
);
event.clipboardData?.setData('agent:nodes', nodesStr);
},
[nodes],
);
const onPasteCapture = useCallback(
(event: ClipboardEvent) => {
const nodes = JSON.parse(
event.clipboardData?.getData('agent:nodes') || '[]',
) as RAGFlowNodeType[] | undefined;
if (Array.isArray(nodes) && nodes.length) {
event.preventDefault();
nodes.forEach((n) => {
duplicateNode(n.id, n.data.label);
});
}
},
[duplicateNode],
);
useEffect(() => {
window.addEventListener('copy', onCopyCapture);
return () => {
window.removeEventListener('copy', onCopyCapture);
};
}, [onCopyCapture]);
useEffect(() => {
window.addEventListener('paste', onPasteCapture);
return () => {
window.removeEventListener('paste', onPasteCapture);
};
}, [onPasteCapture]);
};

View File

@ -10,45 +10,29 @@ import {
NodeMap, NodeMap,
Operator, Operator,
initialAgentValues, initialAgentValues,
initialAkShareValues,
initialArXivValues,
initialBaiduFanyiValues,
initialBeginValues, initialBeginValues,
initialBingValues,
initialCategorizeValues, initialCategorizeValues,
initialChunkerValues,
initialCodeValues, initialCodeValues,
initialConcentratorValues, initialConcentratorValues,
initialCrawlerValues, initialCrawlerValues,
initialDeepLValues,
initialDuckValues,
initialEmailValues, initialEmailValues,
initialExeSqlValues, initialExeSqlValues,
initialGithubValues,
initialGoogleScholarValues,
initialGoogleValues,
initialInvokeValues, initialInvokeValues,
initialIterationStartValues, initialIterationStartValues,
initialIterationValues, initialIterationValues,
initialJin10Values,
initialKeywordExtractValues, initialKeywordExtractValues,
initialMessageValues, initialMessageValues,
initialNoteValues, initialNoteValues,
initialPubMedValues, initialParserValues,
initialQWeatherValues,
initialRelevantValues, initialRelevantValues,
initialRetrievalValues, initialRetrievalValues,
initialRewriteQuestionValues, initialRewriteQuestionValues,
initialSearXNGValues,
initialStringTransformValues, initialStringTransformValues,
initialSwitchValues, initialSwitchValues,
initialTavilyExtractValues, initialTokenizerValues,
initialTavilyValues,
initialTuShareValues,
initialUserFillUpValues, initialUserFillUpValues,
initialWaitingDialogueValues, initialWaitingDialogueValues,
initialWenCaiValues,
initialWikipediaValues,
initialYahooFinanceValues,
} from '../constant'; } from '../constant';
import useGraphStore from '../store'; import useGraphStore from '../store';
import { import {
@ -80,26 +64,9 @@ export const useInitializeOperatorParams = () => {
...initialKeywordExtractValues, ...initialKeywordExtractValues,
llm_id: llmId, llm_id: llmId,
}, },
[Operator.DuckDuckGo]: initialDuckValues,
[Operator.Wikipedia]: initialWikipediaValues,
[Operator.PubMed]: initialPubMedValues,
[Operator.ArXiv]: initialArXivValues,
[Operator.Google]: initialGoogleValues,
[Operator.Bing]: initialBingValues,
[Operator.GoogleScholar]: initialGoogleScholarValues,
[Operator.DeepL]: initialDeepLValues,
[Operator.SearXNG]: initialSearXNGValues,
[Operator.GitHub]: initialGithubValues,
[Operator.BaiduFanyi]: initialBaiduFanyiValues,
[Operator.QWeather]: initialQWeatherValues,
[Operator.ExeSQL]: initialExeSqlValues, [Operator.ExeSQL]: initialExeSqlValues,
[Operator.Switch]: initialSwitchValues, [Operator.Switch]: initialSwitchValues,
[Operator.WenCai]: initialWenCaiValues,
[Operator.AkShare]: initialAkShareValues,
[Operator.YahooFinance]: initialYahooFinanceValues,
[Operator.Jin10]: initialJin10Values,
[Operator.Concentrator]: initialConcentratorValues, [Operator.Concentrator]: initialConcentratorValues,
[Operator.TuShare]: initialTuShareValues,
[Operator.Note]: initialNoteValues, [Operator.Note]: initialNoteValues,
[Operator.Crawler]: initialCrawlerValues, [Operator.Crawler]: initialCrawlerValues,
[Operator.Invoke]: initialInvokeValues, [Operator.Invoke]: initialInvokeValues,
@ -110,10 +77,11 @@ export const useInitializeOperatorParams = () => {
[Operator.WaitingDialogue]: initialWaitingDialogueValues, [Operator.WaitingDialogue]: initialWaitingDialogueValues,
[Operator.Agent]: { ...initialAgentValues, llm_id: llmId }, [Operator.Agent]: { ...initialAgentValues, llm_id: llmId },
[Operator.Tool]: {}, [Operator.Tool]: {},
[Operator.TavilySearch]: initialTavilyValues,
[Operator.UserFillUp]: initialUserFillUpValues, [Operator.UserFillUp]: initialUserFillUpValues,
[Operator.StringTransform]: initialStringTransformValues, [Operator.StringTransform]: initialStringTransformValues,
[Operator.TavilyExtract]: initialTavilyExtractValues, [Operator.Parser]: initialParserValues,
[Operator.Chunker]: initialChunkerValues,
[Operator.Tokenizer]: initialTokenizerValues,
}; };
}, [llmId]); }, [llmId]);

View File

@ -1,70 +0,0 @@
import { omit, pick } from 'lodash';
import { useCallback } from 'react';
import { Operator } from '../constant';
import { useInitializeOperatorParams } from './use-add-node';
export function useAgentToolInitialValues() {
const { initialFormValuesMap } = useInitializeOperatorParams();
const initializeAgentToolValues = useCallback(
(operatorName: Operator) => {
const initialValues = initialFormValuesMap[operatorName];
switch (operatorName) {
case Operator.Retrieval:
return {
...omit(initialValues, 'query'),
description: '',
};
case (Operator.TavilySearch, Operator.TavilyExtract):
return {
api_key: '',
};
case Operator.ExeSQL:
return omit(initialValues, 'sql');
case Operator.Bing:
return omit(initialValues, 'query');
case Operator.YahooFinance:
return omit(initialValues, 'stock_code');
case Operator.Email:
return pick(
initialValues,
'smtp_server',
'smtp_port',
'email',
'password',
'sender_name',
);
case Operator.DuckDuckGo:
return pick(initialValues, 'top_n', 'channel');
case Operator.Wikipedia:
return pick(initialValues, 'top_n', 'language');
case Operator.Google:
return pick(initialValues, 'api_key', 'country', 'language');
case Operator.GoogleScholar:
return omit(initialValues, 'query', 'outputs');
case Operator.ArXiv:
return pick(initialValues, 'top_n', 'sort_by');
case Operator.PubMed:
return pick(initialValues, 'top_n', 'email');
case Operator.GitHub:
return pick(initialValues, 'top_n');
case Operator.WenCai:
return pick(initialValues, 'top_n', 'query_type');
case Operator.Code:
return {};
case Operator.SearXNG:
return pick(initialValues, 'searxng_url', 'top_n');
default:
return initialValues;
}
},
[initialFormValuesMap],
);
return { initializeAgentToolValues };
}

View File

@ -29,7 +29,7 @@ import {
} from 'lucide-react'; } from 'lucide-react';
import { ComponentPropsWithoutRef, useCallback } from 'react'; import { ComponentPropsWithoutRef, useCallback } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import AgentCanvas from './canvas'; import DataFlowCanvas from './canvas';
import { DropdownProvider } from './canvas/context'; import { DropdownProvider } from './canvas/context';
import { useHandleExportOrImportJsonFile } from './hooks/use-export-json'; import { useHandleExportOrImportJsonFile } from './hooks/use-export-json';
import { useFetchDataOnMount } from './hooks/use-fetch-data'; import { useFetchDataOnMount } from './hooks/use-fetch-data';
@ -161,10 +161,10 @@ export default function DataFlow() {
</PageHeader> </PageHeader>
<ReactFlowProvider> <ReactFlowProvider>
<DropdownProvider> <DropdownProvider>
<AgentCanvas <DataFlowCanvas
drawerVisible={chatDrawerVisible} drawerVisible={chatDrawerVisible}
hideDrawer={hideChatDrawer} hideDrawer={hideChatDrawer}
></AgentCanvas> ></DataFlowCanvas>
</DropdownProvider> </DropdownProvider>
</ReactFlowProvider> </ReactFlowProvider>
{fileUploadVisible && ( {fileUploadVisible && (

View File

@ -1,17 +1,3 @@
import { ReactComponent as ArxivIcon } from '@/assets/svg/arxiv.svg';
import { ReactComponent as BingIcon } from '@/assets/svg/bing.svg';
import { ReactComponent as CrawlerIcon } from '@/assets/svg/crawler.svg';
import { ReactComponent as DuckIcon } from '@/assets/svg/duck.svg';
import { ReactComponent as GithubIcon } from '@/assets/svg/github.svg';
import { ReactComponent as GoogleScholarIcon } from '@/assets/svg/google-scholar.svg';
import { ReactComponent as GoogleIcon } from '@/assets/svg/google.svg';
import { ReactComponent as PubMedIcon } from '@/assets/svg/pubmed.svg';
import { ReactComponent as SearXNGIcon } from '@/assets/svg/searxng.svg';
import { ReactComponent as TavilyIcon } from '@/assets/svg/tavily.svg';
import { ReactComponent as WenCaiIcon } from '@/assets/svg/wencai.svg';
import { ReactComponent as WikipediaIcon } from '@/assets/svg/wikipedia.svg';
import { ReactComponent as YahooFinanceIcon } from '@/assets/svg/yahoo-finance.svg';
import { IconFont } from '@/components/icon-font'; import { IconFont } from '@/components/icon-font';
import { cn } from '@/lib/utils'; import { cn } from '@/lib/utils';
import { HousePlus } from 'lucide-react'; import { HousePlus } from 'lucide-react';
@ -39,30 +25,13 @@ export const OperatorIconMap = {
[Operator.Email]: 'sendemail-0', [Operator.Email]: 'sendemail-0',
}; };
export const SVGIconMap = {
[Operator.ArXiv]: ArxivIcon,
[Operator.GitHub]: GithubIcon,
[Operator.Bing]: BingIcon,
[Operator.DuckDuckGo]: DuckIcon,
[Operator.Google]: GoogleIcon,
[Operator.GoogleScholar]: GoogleScholarIcon,
[Operator.PubMed]: PubMedIcon,
[Operator.SearXNG]: SearXNGIcon,
[Operator.TavilyExtract]: TavilyIcon,
[Operator.TavilySearch]: TavilyIcon,
[Operator.Wikipedia]: WikipediaIcon,
[Operator.YahooFinance]: YahooFinanceIcon,
[Operator.WenCai]: WenCaiIcon,
[Operator.Crawler]: CrawlerIcon,
};
const Empty = () => { const Empty = () => {
return <div className="hidden"></div>; return <div className="hidden"></div>;
}; };
const OperatorIcon = ({ name, className }: IProps) => { const OperatorIcon = ({ name, className }: IProps) => {
const Icon = OperatorIconMap[name as keyof typeof OperatorIconMap] || Empty; const Icon = OperatorIconMap[name as keyof typeof OperatorIconMap] || Empty;
const SvgIcon = SVGIconMap[name as keyof typeof SVGIconMap] || Empty; const SvgIcon = Empty;
if (name === Operator.Begin) { if (name === Operator.Begin) {
return ( return (
@ -80,7 +49,7 @@ const OperatorIcon = ({ name, className }: IProps) => {
return typeof Icon === 'string' ? ( return typeof Icon === 'string' ? (
<IconFont name={Icon} className={cn('size-5 ', className)}></IconFont> <IconFont name={Icon} className={cn('size-5 ', className)}></IconFont>
) : ( ) : (
<SvgIcon className={cn('size-5 fill-current', className)}></SvgIcon> <SvgIcon></SvgIcon>
); );
}; };