diff --git a/web/src/constants/agent.ts b/web/src/constants/agent.ts
index 6e388d7a0..f6af4f57c 100644
--- a/web/src/constants/agent.ts
+++ b/web/src/constants/agent.ts
@@ -53,6 +53,10 @@ export enum AgentCategory {
DataflowCanvas = 'dataflow_canvas',
}
+export enum AgentQuery {
+ Category = 'category',
+}
+
export enum DataflowOperator {
Begin = 'File',
Note = 'Note',
@@ -62,3 +66,55 @@ export enum DataflowOperator {
HierarchicalMerger = 'HierarchicalMerger',
Extractor = 'Extractor',
}
+
+export enum Operator {
+ Begin = 'Begin',
+ Retrieval = 'Retrieval',
+ Categorize = 'Categorize',
+ Message = 'Message',
+ Relevant = 'Relevant',
+ RewriteQuestion = 'RewriteQuestion',
+ 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',
+ Switch = 'Switch',
+ WenCai = 'WenCai',
+ AkShare = 'AkShare',
+ YahooFinance = 'YahooFinance',
+ Jin10 = 'Jin10',
+ TuShare = 'TuShare',
+ Note = 'Note',
+ Crawler = 'Crawler',
+ Invoke = 'Invoke',
+ Email = 'Email',
+ Iteration = 'Iteration',
+ IterationStart = 'IterationItem',
+ Code = 'CodeExec',
+ WaitingDialogue = 'WaitingDialogue',
+ Agent = 'Agent',
+ Tool = 'Tool',
+ TavilySearch = 'TavilySearch',
+ TavilyExtract = 'TavilyExtract',
+ UserFillUp = 'UserFillUp',
+ StringTransform = 'StringTransform',
+ SearXNG = 'SearXNG',
+ Placeholder = 'Placeholder',
+ File = 'File', // pipeline
+ Parser = 'Parser',
+ Tokenizer = 'Tokenizer',
+ Splitter = 'Splitter',
+ HierarchicalMerger = 'HierarchicalMerger',
+ Extractor = 'Extractor',
+ Generate = 'Generate',
+}
diff --git a/web/src/hooks/logic-hooks/navigate-hooks.ts b/web/src/hooks/logic-hooks/navigate-hooks.ts
index 042489bac..92f573010 100644
--- a/web/src/hooks/logic-hooks/navigate-hooks.ts
+++ b/web/src/hooks/logic-hooks/navigate-hooks.ts
@@ -1,3 +1,4 @@
+import { AgentCategory, AgentQuery } from '@/constants/agent';
import { NavigateToDataflowResultProps } from '@/pages/dataflow-result/interface';
import { Routes } from '@/routes';
import { useCallback } from 'react';
@@ -70,8 +71,8 @@ export const useNavigatePage = () => {
}, [navigate]);
const navigateToAgent = useCallback(
- (id: string) => () => {
- navigate(`${Routes.Agent}/${id}`);
+ (id: string, category?: AgentCategory) => () => {
+ navigate(`${Routes.Agent}/${id}?${AgentQuery.Category}=${category}`);
},
[navigate],
);
diff --git a/web/src/pages/agent/canvas/index.tsx b/web/src/pages/agent/canvas/index.tsx
index 0bf32d08f..ec81bd9e6 100644
--- a/web/src/pages/agent/canvas/index.tsx
+++ b/web/src/pages/agent/canvas/index.tsx
@@ -56,19 +56,24 @@ import { RagNode } from './node';
import { AgentNode } from './node/agent-node';
import { BeginNode } from './node/begin-node';
import { CategorizeNode } from './node/categorize-node';
-import { InnerNextStepDropdown } from './node/dropdown/next-step-dropdown';
+import { NextStepDropdown } from './node/dropdown/next-step-dropdown';
+import { ExtractorNode } from './node/extractor-node';
+import { FileNode } from './node/file-node';
import { GenerateNode } from './node/generate-node';
import { InvokeNode } from './node/invoke-node';
import { IterationNode, IterationStartNode } from './node/iteration-node';
import { KeywordNode } from './node/keyword-node';
import { MessageNode } from './node/message-node';
import NoteNode from './node/note-node';
+import ParserNode from './node/parser-node';
import { PlaceholderNode } from './node/placeholder-node';
import { RelevantNode } from './node/relevant-node';
import { RetrievalNode } from './node/retrieval-node';
import { RewriteNode } from './node/rewrite-node';
+import { SplitterNode } from './node/splitter-node';
import { SwitchNode } from './node/switch-node';
import { TemplateNode } from './node/template-node';
+import TokenizerNode from './node/tokenizer-node';
import { ToolNode } from './node/tool-node';
export const nodeTypes: NodeTypes = {
@@ -91,6 +96,11 @@ export const nodeTypes: NodeTypes = {
iterationStartNode: IterationStartNode,
agentNode: AgentNode,
toolNode: ToolNode,
+ fileNode: FileNode,
+ parserNode: ParserNode,
+ tokenizerNode: TokenizerNode,
+ splitterNode: SplitterNode,
+ contextNode: ExtractorNode,
};
const edgeTypes = {
@@ -194,6 +204,7 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) {
getConnectionStartContext,
shouldPreventClose,
onMove,
+ nodeId,
} = useConnectionDrag(
reactFlowInstance,
originalOnConnect,
@@ -312,7 +323,7 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) {
}
}
>
- {
removePlaceholderNode();
hideModal();
@@ -320,9 +331,10 @@ function AgentCanvas({ drawerVisible, hideDrawer }: IProps) {
}}
position={dropdownPosition}
onNodeCreated={onNodeCreated}
+ nodeId={nodeId}
>
-
+
)}
diff --git a/web/src/pages/agent/canvas/node/card.tsx b/web/src/pages/agent/canvas/node/card.tsx
index 042ca45e0..cd5e1ae09 100644
--- a/web/src/pages/agent/canvas/node/card.tsx
+++ b/web/src/pages/agent/canvas/node/card.tsx
@@ -17,6 +17,9 @@ import {
SelectValue,
} from '@/components/ui/select';
+import { cn } from '@/lib/utils';
+import { PropsWithChildren } from 'react';
+
export function CardWithForm() {
return (
@@ -55,3 +58,13 @@ export function CardWithForm() {
);
}
+
+type LabelCardProps = {
+ className?: string;
+} & PropsWithChildren;
+
+export function LabelCard({ children, className }: LabelCardProps) {
+ return (
+
{children}
+ );
+}
diff --git a/web/src/pages/agent/canvas/node/dropdown/accordion-operators.tsx b/web/src/pages/agent/canvas/node/dropdown/accordion-operators.tsx
new file mode 100644
index 000000000..3ea40f986
--- /dev/null
+++ b/web/src/pages/agent/canvas/node/dropdown/accordion-operators.tsx
@@ -0,0 +1,196 @@
+import {
+ Accordion,
+ AccordionContent,
+ AccordionItem,
+ AccordionTrigger,
+} from '@/components/ui/accordion';
+import { Operator } from '@/constants/agent';
+import useGraphStore from '@/pages/agent/store';
+import { useCallback, useMemo } from 'react';
+import { useTranslation } from 'react-i18next';
+import { OperatorItemList } from './operator-item-list';
+
+export function AccordionOperators({
+ isCustomDropdown = false,
+ mousePosition,
+}: {
+ isCustomDropdown?: boolean;
+ mousePosition?: { x: number; y: number };
+}) {
+ const { t } = useTranslation();
+
+ return (
+
+
+
+ {t('flow.foundation')}
+
+
+
+
+
+
+
+ {t('flow.dialog')}
+
+
+
+
+
+
+
+ {t('flow.flow')}
+
+
+
+
+
+
+
+ {t('flow.dataManipulation')}
+
+
+
+
+
+
+
+ {t('flow.tools')}
+
+
+
+
+
+
+ );
+}
+
+// Limit the number of operators of a certain type on the canvas to only one
+function useRestrictSingleOperatorOnCanvas() {
+ const { findNodeByName } = useGraphStore((state) => state);
+
+ const restrictSingleOperatorOnCanvas = useCallback(
+ (singleOperators: Operator[]) => {
+ const list: Operator[] = [];
+ singleOperators.forEach((operator) => {
+ if (!findNodeByName(operator)) {
+ list.push(operator);
+ }
+ });
+ return list;
+ },
+ [findNodeByName],
+ );
+
+ return restrictSingleOperatorOnCanvas;
+}
+
+export function PipelineAccordionOperators({
+ isCustomDropdown = false,
+ mousePosition,
+ nodeId,
+}: {
+ isCustomDropdown?: boolean;
+ mousePosition?: { x: number; y: number };
+ nodeId?: string;
+}) {
+ const restrictSingleOperatorOnCanvas = useRestrictSingleOperatorOnCanvas();
+ const { getOperatorTypeFromId } = useGraphStore((state) => state);
+
+ const operators = useMemo(() => {
+ let list = [
+ ...restrictSingleOperatorOnCanvas([Operator.Parser, Operator.Tokenizer]),
+ ];
+ list.push(Operator.Extractor);
+ return list;
+ }, [restrictSingleOperatorOnCanvas]);
+
+ const chunkerOperators = useMemo(() => {
+ return [
+ ...restrictSingleOperatorOnCanvas([
+ Operator.Splitter,
+ Operator.HierarchicalMerger,
+ ]),
+ ];
+ }, [restrictSingleOperatorOnCanvas]);
+
+ const showChunker = useMemo(() => {
+ return (
+ getOperatorTypeFromId(nodeId) !== Operator.Extractor &&
+ chunkerOperators.length > 0
+ );
+ }, [chunkerOperators.length, getOperatorTypeFromId, nodeId]);
+
+ return (
+ <>
+
+ {showChunker && (
+
+
+ Chunker
+
+
+
+
+
+ )}
+ >
+ );
+}
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 bc7bf4577..dd2945b77 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
@@ -1,230 +1,33 @@
-import {
- Accordion,
- AccordionContent,
- AccordionItem,
- AccordionTrigger,
-} from '@/components/ui/accordion';
import {
DropdownMenu,
DropdownMenuContent,
- DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
-import {
- Tooltip,
- TooltipContent,
- TooltipTrigger,
-} from '@/components/ui/tooltip';
import { IModalProps } from '@/interfaces/common';
-import { Operator } from '@/pages/agent/constant';
-import { AgentInstanceContext, HandleContext } from '@/pages/agent/context';
-import OperatorIcon from '@/pages/agent/operator-icon';
-import { Position } from '@xyflow/react';
+import { useIsPipeline } from '@/pages/agent/hooks/use-is-pipeline';
import { t } from 'i18next';
-import { lowerFirst } from 'lodash';
+import { PropsWithChildren, memo, useEffect, useRef } from 'react';
import {
- PropsWithChildren,
- createContext,
- memo,
- useContext,
- useEffect,
- useRef,
-} from 'react';
-import { useTranslation } from 'react-i18next';
-
-type OperatorItemProps = {
- operators: Operator[];
- isCustomDropdown?: boolean;
- mousePosition?: { x: number; y: number };
-};
-
-const HideModalContext = createContext['showModal']>(() => {});
-const OnNodeCreatedContext = createContext<
- ((newNodeId: string) => void) | undefined
->(undefined);
-
-function OperatorItemList({
- operators,
- isCustomDropdown = false,
- mousePosition,
-}: OperatorItemProps) {
- const { addCanvasNode } = useContext(AgentInstanceContext);
- const handleContext = useContext(HandleContext);
- const hideModal = useContext(HideModalContext);
- const onNodeCreated = useContext(OnNodeCreatedContext);
- const { t } = useTranslation();
-
- const handleClick =
- (operator: Operator): React.MouseEventHandler =>
- (e) => {
- const contextData = handleContext || {
- nodeId: '',
- id: '',
- type: 'source' as const,
- position: Position.Right,
- isFromConnectionDrag: true,
- };
-
- const mockEvent = mousePosition
- ? {
- clientX: mousePosition.x,
- clientY: mousePosition.y,
- }
- : e;
-
- const newNodeId = addCanvasNode(operator, contextData)(mockEvent);
-
- if (onNodeCreated && newNodeId) {
- onNodeCreated(newNodeId);
- }
-
- hideModal?.();
- };
-
- const renderOperatorItem = (operator: Operator) => {
- const commonContent = (
-
-
- {t(`flow.${lowerFirst(operator)}`)}
-
- );
-
- return (
-
-
- {isCustomDropdown ? (
- {commonContent}
- ) : (
- hideModal?.()}
- >
-
- {t(`flow.${lowerFirst(operator)}`)}
-
- )}
-
-
- {t(`flow.${lowerFirst(operator)}Description`)}
-
-
- );
- };
-
- return {operators.map(renderOperatorItem)}
;
-}
-
-function AccordionOperators({
- isCustomDropdown = false,
- mousePosition,
-}: {
- isCustomDropdown?: boolean;
- mousePosition?: { x: number; y: number };
-}) {
- return (
-
-
-
- {t('flow.foundation')}
-
-
-
-
-
-
-
- {t('flow.dialog')}
-
-
-
-
-
-
-
- {t('flow.flow')}
-
-
-
-
-
-
-
- {t('flow.dataManipulation')}
-
-
-
-
-
-
-
- {t('flow.tools')}
-
-
-
-
-
-
- );
-}
+ AccordionOperators,
+ PipelineAccordionOperators,
+} from './accordion-operators';
+import { HideModalContext, OnNodeCreatedContext } from './operator-item-list';
export function InnerNextStepDropdown({
children,
hideModal,
position,
onNodeCreated,
+ nodeId,
}: PropsWithChildren &
IModalProps & {
position?: { x: number; y: number };
onNodeCreated?: (newNodeId: string) => void;
+ nodeId?: string;
}) {
const dropdownRef = useRef(null);
+ const isPipeline = useIsPipeline();
useEffect(() => {
if (position && hideModal) {
@@ -260,10 +63,18 @@ export function InnerNextStepDropdown({
-
+ {isPipeline ? (
+
+ ) : (
+
+ )}
@@ -287,7 +98,11 @@ export function InnerNextStepDropdown({
>
{t('flow.nextStep')}
-
+ {isPipeline ? (
+
+ ) : (
+
+ )}
diff --git a/web/src/pages/agent/canvas/node/dropdown/operator-item-list.tsx b/web/src/pages/agent/canvas/node/dropdown/operator-item-list.tsx
new file mode 100644
index 000000000..30480bd50
--- /dev/null
+++ b/web/src/pages/agent/canvas/node/dropdown/operator-item-list.tsx
@@ -0,0 +1,100 @@
+import { DropdownMenuItem } from '@/components/ui/dropdown-menu';
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from '@/components/ui/tooltip';
+import { Operator } from '@/constants/agent';
+import { IModalProps } from '@/interfaces/common';
+import { AgentInstanceContext, HandleContext } from '@/pages/agent/context';
+import OperatorIcon from '@/pages/agent/operator-icon';
+import { Position } from '@xyflow/react';
+import { lowerFirst } from 'lodash';
+import { createContext, useContext } from 'react';
+import { useTranslation } from 'react-i18next';
+
+export type OperatorItemProps = {
+ operators: Operator[];
+ isCustomDropdown?: boolean;
+ mousePosition?: { x: number; y: number };
+};
+
+export const HideModalContext = createContext['showModal']>(
+ () => {},
+);
+export const OnNodeCreatedContext = createContext<
+ ((newNodeId: string) => void) | undefined
+>(undefined);
+
+export function OperatorItemList({
+ operators,
+ isCustomDropdown = false,
+ mousePosition,
+}: OperatorItemProps) {
+ const { addCanvasNode } = useContext(AgentInstanceContext);
+ const handleContext = useContext(HandleContext);
+ const hideModal = useContext(HideModalContext);
+ const onNodeCreated = useContext(OnNodeCreatedContext);
+ const { t } = useTranslation();
+
+ const handleClick =
+ (operator: Operator): React.MouseEventHandler =>
+ (e) => {
+ const contextData = handleContext || {
+ nodeId: '',
+ id: '',
+ type: 'source' as const,
+ position: Position.Right,
+ isFromConnectionDrag: true,
+ };
+
+ const mockEvent = mousePosition
+ ? {
+ clientX: mousePosition.x,
+ clientY: mousePosition.y,
+ }
+ : e;
+
+ const newNodeId = addCanvasNode(operator, contextData)(mockEvent);
+
+ if (onNodeCreated && newNodeId) {
+ onNodeCreated(newNodeId);
+ }
+
+ hideModal?.();
+ };
+
+ const renderOperatorItem = (operator: Operator) => {
+ const commonContent = (
+
+
+ {t(`flow.${lowerFirst(operator)}`)}
+
+ );
+
+ return (
+
+
+ {isCustomDropdown ? (
+ {commonContent}
+ ) : (
+ hideModal?.()}
+ >
+
+ {t(`flow.${lowerFirst(operator)}`)}
+
+ )}
+
+
+ {t(`flow.${lowerFirst(operator)}Description`)}
+
+
+ );
+ };
+
+ return {operators.map(renderOperatorItem)}
;
+}
diff --git a/web/src/pages/agent/canvas/node/extractor-node.tsx b/web/src/pages/agent/canvas/node/extractor-node.tsx
new file mode 100644
index 000000000..8b2e03483
--- /dev/null
+++ b/web/src/pages/agent/canvas/node/extractor-node.tsx
@@ -0,0 +1,18 @@
+import LLMLabel from '@/components/llm-select/llm-label';
+import { IRagNode } from '@/interfaces/database/agent';
+import { NodeProps } from '@xyflow/react';
+import { get } from 'lodash';
+import { LabelCard } from './card';
+import { RagNode } from './index';
+
+export function ExtractorNode({ ...props }: NodeProps) {
+ const { data } = props;
+
+ return (
+
+
+
+
+
+ );
+}
diff --git a/web/src/pages/agent/canvas/node/file-node.tsx b/web/src/pages/agent/canvas/node/file-node.tsx
new file mode 100644
index 000000000..41e0b2507
--- /dev/null
+++ b/web/src/pages/agent/canvas/node/file-node.tsx
@@ -0,0 +1,62 @@
+import { IBeginNode } from '@/interfaces/database/flow';
+import { cn } from '@/lib/utils';
+import { NodeProps, Position } from '@xyflow/react';
+import get from 'lodash/get';
+import { memo } from 'react';
+import { useTranslation } from 'react-i18next';
+import {
+ BeginQueryType,
+ BeginQueryTypeIconMap,
+ NodeHandleId,
+ Operator,
+} from '../../constant';
+import { BeginQuery } from '../../interface';
+import OperatorIcon from '../../operator-icon';
+import { CommonHandle } from './handle';
+import { RightHandleStyle } from './handle-icon';
+import styles from './index.less';
+import { NodeWrapper } from './node-wrapper';
+
+// TODO: do not allow other nodes to connect to this node
+function InnerFileNode({ data, id, selected }: NodeProps) {
+ const { t } = useTranslation();
+ const inputs: Record = get(data, 'form.inputs', {});
+
+ return (
+
+
+
+
+
+
+ {t(`dataflow.begin`)}
+
+
+
+ {Object.entries(inputs).map(([key, val], idx) => {
+ const Icon = BeginQueryTypeIconMap[val.type as BeginQueryType];
+ return (
+
+
+
+ {val.name}
+ {val.optional ? 'Yes' : 'No'}
+
+ );
+ })}
+
+
+ );
+}
+
+export const FileNode = memo(InnerFileNode);
diff --git a/web/src/pages/agent/canvas/node/handle.tsx b/web/src/pages/agent/canvas/node/handle.tsx
index 43ee94bc8..2f7530fd6 100644
--- a/web/src/pages/agent/canvas/node/handle.tsx
+++ b/web/src/pages/agent/canvas/node/handle.tsx
@@ -6,7 +6,7 @@ import { useMemo } from 'react';
import { NodeHandleId } from '../../constant';
import { HandleContext } from '../../context';
import { useDropdownManager } from '../context';
-import { InnerNextStepDropdown } from './dropdown/next-step-dropdown';
+import { NextStepDropdown } from './dropdown/next-step-dropdown';
export function CommonHandle({
className,
@@ -50,14 +50,15 @@ export function CommonHandle({
>
{visible && (
- {
hideModal();
clearActiveDropdown();
}}
>
-
+
)}
diff --git a/web/src/pages/agent/canvas/node/index.tsx b/web/src/pages/agent/canvas/node/index.tsx
index ccd00b9ca..953bb6daa 100644
--- a/web/src/pages/agent/canvas/node/index.tsx
+++ b/web/src/pages/agent/canvas/node/index.tsx
@@ -2,7 +2,7 @@ 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 { needsSingleStepDebugging, showCopyIcon } from '../../utils';
import { CommonHandle, LeftEndHandle } from './handle';
import { RightHandleStyle } from './handle-icon';
import NodeHeader from './node-header';
@@ -21,6 +21,7 @@ function InnerRagNode({
id={id}
label={data.label}
showRun={needsSingleStepDebugging(data.label)}
+ showCopy={showCopyIcon(data.label)}
>
diff --git a/web/src/pages/agent/canvas/node/node-header.tsx b/web/src/pages/agent/canvas/node/node-header.tsx
index cada3deee..de5b222ed 100644
--- a/web/src/pages/agent/canvas/node/node-header.tsx
+++ b/web/src/pages/agent/canvas/node/node-header.tsx
@@ -9,6 +9,7 @@ interface IProps {
gap?: number;
className?: string;
wrapperClassName?: string;
+ icon?: React.ReactNode;
}
const InnerNodeHeader = ({
@@ -16,11 +17,12 @@ const InnerNodeHeader = ({
name,
className,
wrapperClassName,
+ icon,
}: IProps) => {
return (
-
+ {icon ||
}
{name}
diff --git a/web/src/pages/agent/canvas/node/parser-node.tsx b/web/src/pages/agent/canvas/node/parser-node.tsx
new file mode 100644
index 000000000..15539d0b8
--- /dev/null
+++ b/web/src/pages/agent/canvas/node/parser-node.tsx
@@ -0,0 +1,57 @@
+import { NodeCollapsible } from '@/components/collapse';
+import { BaseNode } from '@/interfaces/database/agent';
+import { NodeProps, Position } from '@xyflow/react';
+import { memo } from 'react';
+import { useTranslation } from 'react-i18next';
+import { NodeHandleId } from '../../constant';
+import { ParserFormSchemaType } from '../../form/parser-form';
+import { LabelCard } from './card';
+import { CommonHandle } from './handle';
+import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
+import NodeHeader from './node-header';
+import { NodeWrapper } from './node-wrapper';
+
+function ParserNode({
+ id,
+ data,
+ isConnectable = true,
+ selected,
+}: NodeProps
>) {
+ const { t } = useTranslation();
+ return (
+
+
+
+
+
+
+ {(x, idx) => (
+
+ Parser {idx + 1}
+ {t(`dataflow.fileFormatOptions.${x.fileFormat}`)}
+
+ )}
+
+
+ );
+}
+
+export default memo(ParserNode);
diff --git a/web/src/pages/agent/canvas/node/splitter-node.tsx b/web/src/pages/agent/canvas/node/splitter-node.tsx
new file mode 100644
index 000000000..5797bd5e3
--- /dev/null
+++ b/web/src/pages/agent/canvas/node/splitter-node.tsx
@@ -0,0 +1,58 @@
+import { IRagNode } from '@/interfaces/database/flow';
+import { NodeProps, Position } from '@xyflow/react';
+import { PropsWithChildren, memo } from 'react';
+import { NodeHandleId, Operator } from '../../constant';
+import OperatorIcon from '../../operator-icon';
+import { LabelCard } from './card';
+import { CommonHandle } from './handle';
+import { LeftHandleStyle, RightHandleStyle } from './handle-icon';
+import NodeHeader from './node-header';
+import { NodeWrapper } from './node-wrapper';
+import { ToolBar } from './toolbar';
+
+type RagNodeProps = NodeProps & PropsWithChildren;
+function InnerSplitterNode({
+ id,
+ data,
+ isConnectable = true,
+ selected,
+}: RagNodeProps) {
+ return (
+
+
+
+
+ }
+ >
+ {data.name}
+
+
+ );
+}
+
+export const SplitterNode = memo(InnerSplitterNode);
diff --git a/web/src/pages/agent/canvas/node/tokenizer-node.tsx b/web/src/pages/agent/canvas/node/tokenizer-node.tsx
new file mode 100644
index 000000000..20b261bf4
--- /dev/null
+++ b/web/src/pages/agent/canvas/node/tokenizer-node.tsx
@@ -0,0 +1,55 @@
+import { BaseNode } from '@/interfaces/database/agent';
+import { NodeProps, Position } from '@xyflow/react';
+import { memo } from 'react';
+import { useTranslation } from 'react-i18next';
+import { NodeHandleId } from '../../constant';
+import { TokenizerFormSchemaType } from '../../form/tokenizer-form';
+import { LabelCard } from './card';
+import { CommonHandle } from './handle';
+import { LeftHandleStyle } 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>) {
+ const { t } = useTranslation();
+
+ return (
+
+
+
+
+
+
+ {t('dataflow.searchMethod')}
+
+
+ {data.form?.search_method.map((x) => (
+ - {t(`dataflow.tokenizerSearchMethodOptions.${x}`)}
+ ))}
+
+
+
+
+ );
+}
+
+export default memo(TokenizerNode);
diff --git a/web/src/pages/agent/canvas/node/toolbar.tsx b/web/src/pages/agent/canvas/node/toolbar.tsx
index f36cfe2af..565378575 100644
--- a/web/src/pages/agent/canvas/node/toolbar.tsx
+++ b/web/src/pages/agent/canvas/node/toolbar.tsx
@@ -28,6 +28,7 @@ type ToolBarProps = {
label: string;
id: string;
showRun?: boolean;
+ showCopy?: boolean;
} & PropsWithChildren;
export function ToolBar({
@@ -36,6 +37,7 @@ export function ToolBar({
label,
id,
showRun = true,
+ showCopy = true,
}: ToolBarProps) {
const deleteNodeById = useGraphStore((store) => store.deleteNodeById);
const deleteIterationNodeById = useGraphStore(
@@ -74,10 +76,12 @@ export function ToolBar({
- )}{' '}
-
-
-
+ )}
+ {showCopy && (
+
+
+
+ )}
diff --git a/web/src/pages/agent/constant.tsx b/web/src/pages/agent/constant/index.tsx
similarity index 94%
rename from web/src/pages/agent/constant.tsx
rename to web/src/pages/agent/constant/index.tsx
index 35a67cae4..c444b830e 100644
--- a/web/src/pages/agent/constant.tsx
+++ b/web/src/pages/agent/constant/index.tsx
@@ -6,9 +6,13 @@ import {
AgentGlobals,
AgentGlobalsSysQueryWithBrace,
CodeTemplateStrMap,
+ Operator,
ProgrammingLanguage,
initialLlmBaseValues,
} from '@/constants/agent';
+export { Operator } from '@/constants/agent';
+
+export * from './pipeline';
export enum AgentDialogueMode {
Conversational = 'conversational',
@@ -43,51 +47,6 @@ import {
export const BeginId = 'begin';
-export enum Operator {
- Begin = 'Begin',
- Retrieval = 'Retrieval',
- Categorize = 'Categorize',
- Message = 'Message',
- Relevant = 'Relevant',
- RewriteQuestion = 'RewriteQuestion',
- 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',
- Switch = 'Switch',
- WenCai = 'WenCai',
- AkShare = 'AkShare',
- YahooFinance = 'YahooFinance',
- Jin10 = 'Jin10',
- TuShare = 'TuShare',
- Note = 'Note',
- Crawler = 'Crawler',
- Invoke = 'Invoke',
- Email = 'Email',
- Iteration = 'Iteration',
- IterationStart = 'IterationItem',
- Code = 'CodeExec',
- WaitingDialogue = 'WaitingDialogue',
- Agent = 'Agent',
- Tool = 'Tool',
- TavilySearch = 'TavilySearch',
- TavilyExtract = 'TavilyExtract',
- UserFillUp = 'UserFillUp',
- StringTransform = 'StringTransform',
- SearXNG = 'SearXNG',
- Placeholder = 'Placeholder',
-}
-
export const SwitchLogicOperatorOptions = ['and', 'or'];
export const CommonOperatorList = Object.values(Operator).filter(
@@ -833,6 +792,11 @@ export const RestrictedUpstreamMap = {
[Operator.UserFillUp]: [Operator.Begin],
[Operator.Tool]: [Operator.Begin],
[Operator.Placeholder]: [Operator.Begin],
+ [Operator.Parser]: [Operator.Begin],
+ [Operator.Splitter]: [Operator.Begin],
+ [Operator.HierarchicalMerger]: [Operator.Begin],
+ [Operator.Tokenizer]: [Operator.Begin],
+ [Operator.Extractor]: [Operator.Begin],
};
export const NodeMap = {
@@ -878,6 +842,12 @@ export const NodeMap = {
[Operator.StringTransform]: 'ragNode',
[Operator.TavilyExtract]: 'ragNode',
[Operator.Placeholder]: 'placeholderNode',
+ [Operator.File]: 'fileNode',
+ [Operator.Parser]: 'parserNode',
+ [Operator.Tokenizer]: 'tokenizerNode',
+ [Operator.Splitter]: 'splitterNode',
+ [Operator.HierarchicalMerger]: 'splitterNode',
+ [Operator.Extractor]: 'contextNode',
};
export enum BeginQueryType {
@@ -906,6 +876,21 @@ export const NoDebugOperatorsList = [
Operator.Iteration,
Operator.UserFillUp,
Operator.IterationStart,
+ Operator.File,
+ Operator.Parser,
+ Operator.Tokenizer,
+ Operator.Splitter,
+ Operator.HierarchicalMerger,
+ Operator.Extractor,
+];
+
+export const NoCopyOperatorsList = [
+ Operator.File,
+ Operator.Parser,
+ Operator.Tokenizer,
+ Operator.Splitter,
+ Operator.HierarchicalMerger,
+ Operator.Extractor,
];
export enum NodeHandleId {
diff --git a/web/src/pages/agent/constant/pipeline.tsx b/web/src/pages/agent/constant/pipeline.tsx
new file mode 100644
index 000000000..78d4b3ac9
--- /dev/null
+++ b/web/src/pages/agent/constant/pipeline.tsx
@@ -0,0 +1,272 @@
+import { ParseDocumentType } from '@/components/layout-recognize-form-field';
+import {
+ initialLlmBaseValues,
+ DataflowOperator as Operator,
+} from '@/constants/agent';
+
+export enum FileType {
+ PDF = 'pdf',
+ Spreadsheet = 'spreadsheet',
+ Image = 'image',
+ Email = 'email',
+ TextMarkdown = 'text&markdown',
+ Docx = 'word',
+ PowerPoint = 'slides',
+ Video = 'video',
+ Audio = 'audio',
+}
+
+export enum PdfOutputFormat {
+ Json = 'json',
+ Markdown = 'markdown',
+}
+
+export enum SpreadsheetOutputFormat {
+ Json = 'json',
+ Html = 'html',
+}
+
+export enum ImageOutputFormat {
+ Text = 'text',
+}
+
+export enum EmailOutputFormat {
+ Json = 'json',
+ Text = 'text',
+}
+
+export enum TextMarkdownOutputFormat {
+ Text = 'text',
+}
+
+export enum DocxOutputFormat {
+ Markdown = 'markdown',
+ Json = 'json',
+}
+
+export enum PptOutputFormat {
+ Json = 'json',
+}
+
+export enum VideoOutputFormat {
+ Json = 'json',
+}
+
+export enum AudioOutputFormat {
+ Text = 'text',
+}
+
+export const OutputFormatMap = {
+ [FileType.PDF]: PdfOutputFormat,
+ [FileType.Spreadsheet]: SpreadsheetOutputFormat,
+ [FileType.Image]: ImageOutputFormat,
+ [FileType.Email]: EmailOutputFormat,
+ [FileType.TextMarkdown]: TextMarkdownOutputFormat,
+ [FileType.Docx]: DocxOutputFormat,
+ [FileType.PowerPoint]: PptOutputFormat,
+ [FileType.Video]: VideoOutputFormat,
+ [FileType.Audio]: AudioOutputFormat,
+};
+
+export const InitialOutputFormatMap = {
+ [FileType.PDF]: PdfOutputFormat.Json,
+ [FileType.Spreadsheet]: SpreadsheetOutputFormat.Html,
+ [FileType.Image]: ImageOutputFormat.Text,
+ [FileType.Email]: EmailOutputFormat.Text,
+ [FileType.TextMarkdown]: TextMarkdownOutputFormat.Text,
+ [FileType.Docx]: DocxOutputFormat.Json,
+ [FileType.PowerPoint]: PptOutputFormat.Json,
+ [FileType.Video]: VideoOutputFormat.Json,
+ [FileType.Audio]: AudioOutputFormat.Text,
+};
+
+export enum ContextGeneratorFieldName {
+ Summary = 'summary',
+ Keywords = 'keywords',
+ Questions = 'questions',
+ Metadata = 'metadata',
+}
+
+export const FileId = 'File'; // BeginId
+
+export enum TokenizerSearchMethod {
+ Embedding = 'embedding',
+ FullText = 'full_text',
+}
+
+export enum ImageParseMethod {
+ OCR = 'ocr',
+}
+
+export enum TokenizerFields {
+ Text = 'text',
+ Questions = 'questions',
+ Summary = 'summary',
+}
+
+export enum ParserFields {
+ From = 'from',
+ To = 'to',
+ Cc = 'cc',
+ Bcc = 'bcc',
+ Date = 'date',
+ Subject = 'subject',
+ Body = 'body',
+ Attachments = 'attachments',
+}
+
+// initialBeginValues
+export const initialFileValues = {
+ outputs: {
+ name: {
+ type: 'string',
+ value: '',
+ },
+ file: {
+ type: 'Object',
+ value: {},
+ },
+ },
+};
+
+export const initialTokenizerValues = {
+ search_method: [
+ TokenizerSearchMethod.Embedding,
+ TokenizerSearchMethod.FullText,
+ ],
+ filename_embd_weight: 0.1,
+ fields: TokenizerFields.Text,
+ outputs: {},
+};
+
+export enum StringTransformMethod {
+ Merge = 'merge',
+ Split = 'split',
+}
+
+export enum StringTransformDelimiter {
+ Comma = ',',
+ Semicolon = ';',
+ Period = '.',
+ LineBreak = '\n',
+ Tab = '\t',
+ Space = ' ',
+}
+
+export const initialParserValues = {
+ outputs: {
+ markdown: { type: 'string', value: '' },
+ text: { type: 'string', value: '' },
+ html: { type: 'string', value: '' },
+ json: { type: 'Array
-
-
-
-
-
+
+
+
+
+
+
+
{embedVisible && (
)}
+
+ {pipelineLogSheetVisible && (
+
+ )}
);
}
diff --git a/web/src/pages/agent/pipeline-log-sheet/dataflow-timeline.tsx b/web/src/pages/agent/pipeline-log-sheet/dataflow-timeline.tsx
new file mode 100644
index 000000000..e15465baf
--- /dev/null
+++ b/web/src/pages/agent/pipeline-log-sheet/dataflow-timeline.tsx
@@ -0,0 +1,137 @@
+import {
+ Timeline,
+ TimelineContent,
+ TimelineHeader,
+ TimelineIndicator,
+ TimelineItem,
+ TimelineSeparator,
+ TimelineTitle,
+} from '@/components/originui/timeline';
+import { Progress } from '@/components/ui/progress';
+import { ITraceData } from '@/interfaces/database/agent';
+import { cn } from '@/lib/utils';
+import { isEmpty } from 'lodash';
+import { File } from 'lucide-react';
+import { useCallback } from 'react';
+import { Operator } from '../constant';
+import OperatorIcon from '../operator-icon';
+import useGraphStore from '../store';
+
+export type DataflowTimelineProps = {
+ traceList?: ITraceData[];
+};
+
+const END = 'END';
+
+interface DataflowTrace {
+ datetime: string;
+ elapsed_time: number;
+ message: string;
+ progress: number;
+ timestamp: number;
+}
+export function DataflowTimeline({ traceList }: DataflowTimelineProps) {
+ const getNode = useGraphStore((state) => state.getNode);
+
+ const getNodeData = useCallback(
+ (componentId: string) => {
+ return getNode(componentId)?.data;
+ },
+ [getNode],
+ );
+
+ const getNodeLabel = useCallback(
+ (componentId: string) => {
+ return getNodeData(componentId)?.label as Operator;
+ },
+ [getNodeData],
+ );
+
+ return (
+
+ {Array.isArray(traceList) &&
+ traceList?.map((item, index) => {
+ const traces = item.trace as DataflowTrace[];
+ const nodeLabel = getNodeLabel(item.component_id);
+
+ const latest = traces[traces.length - 1];
+ const progress = latest.progress * 100;
+
+ return (
+
+
+
+
+
+
+
+ {getNodeData(item.component_id)?.name || END}
+
+
+
+
+ {progress.toFixed(2)}%
+
+
+
+
+ {traces
+ .filter((x) => !isEmpty(x.message))
+ .map((x, idx) => (
+
+ {x.datetime}
+ {item.component_id !== 'END' && (
+
+ {x.message}
+
+ )}
+
+ {x.elapsed_time.toString().slice(0, 6)}s
+
+
+ ))}
+
+
+
+
+ {item.component_id === END ? (
+
+ ) : nodeLabel === Operator.Begin ? (
+
+ ) : (
+
+ )}
+
+
+
+ );
+ })}
+
+ );
+}
diff --git a/web/src/pages/agent/pipeline-log-sheet/index.tsx b/web/src/pages/agent/pipeline-log-sheet/index.tsx
new file mode 100644
index 000000000..965882478
--- /dev/null
+++ b/web/src/pages/agent/pipeline-log-sheet/index.tsx
@@ -0,0 +1,114 @@
+import { SkeletonCard } from '@/components/skeleton-card';
+import { Button } from '@/components/ui/button';
+import {
+ Sheet,
+ SheetContent,
+ SheetHeader,
+ SheetTitle,
+} from '@/components/ui/sheet';
+import { useNavigatePage } from '@/hooks/logic-hooks/navigate-hooks';
+import { useFetchAgent } from '@/hooks/use-agent-request';
+import { IModalProps } from '@/interfaces/common';
+import { cn } from '@/lib/utils';
+import { PipelineResultSearchParams } from '@/pages/dataflow-result/constant';
+import {
+ ArrowUpRight,
+ CirclePause,
+ Logs,
+ SquareArrowOutUpRight,
+} from 'lucide-react';
+import { useTranslation } from 'react-i18next';
+import 'react18-json-view/src/style.css';
+import { useParams } from 'umi';
+import {
+ isEndOutputEmpty,
+ useDownloadOutput,
+} from '../hooks/use-download-output';
+import { UseFetchLogReturnType } from '../hooks/use-fetch-pipeline-log';
+import { DataflowTimeline } from './dataflow-timeline';
+
+type LogSheetProps = IModalProps & {
+ handleCancel(): void;
+ uploadedFileData?: Record;
+} & Pick<
+ UseFetchLogReturnType,
+ 'isCompleted' | 'isLogEmpty' | 'isParsing' | 'logs' | 'messageId'
+ >;
+
+export function PipelineLogSheet({
+ hideModal,
+ isParsing,
+ logs,
+ handleCancel,
+ isCompleted,
+ isLogEmpty,
+ messageId,
+ uploadedFileData,
+}: LogSheetProps) {
+ const { t } = useTranslation();
+ const { id } = useParams();
+ const { data: agent } = useFetchAgent();
+
+ const { handleDownloadJson } = useDownloadOutput(logs);
+ const { navigateToDataflowResult } = useNavigatePage();
+
+ return (
+
+ e.preventDefault()}
+ >
+
+
+ {t('flow.log')}
+ {isCompleted && (
+
+ )}
+
+
+
+ {isLogEmpty ? (
+
+ ) : (
+
+ )}
+
+
+ {isParsing ? (
+
+ ) : (
+
+ )}
+
+
+
+ );
+}
diff --git a/web/src/pages/agent/utils.ts b/web/src/pages/agent/utils.ts
index b8ba36e57..c073fc578 100644
--- a/web/src/pages/agent/utils.ts
+++ b/web/src/pages/agent/utils.ts
@@ -14,6 +14,7 @@ import pipe from 'lodash/fp/pipe';
import isObject from 'lodash/isObject';
import {
CategorizeAnchorPointPositions,
+ NoCopyOperatorsList,
NoDebugOperatorsList,
NodeHandleId,
Operator,
@@ -403,6 +404,10 @@ export const needsSingleStepDebugging = (label: string) => {
return !NoDebugOperatorsList.some((x) => (label as Operator) === x);
};
+export function showCopyIcon(label: string) {
+ return !NoCopyOperatorsList.some((x) => (label as Operator) === x);
+}
+
// Get the coordinates of the node relative to the Iteration node
export function getRelativePositionToIterationNode(
nodes: RAGFlowNodeType[],
@@ -464,7 +469,9 @@ export function convertToStringArray(
return list.map((x) => x.value);
}
-export function convertToObjectArray(list: Array) {
+export function convertToObjectArray(
+ list: Array,
+) {
if (!Array.isArray(list)) {
return [];
}
@@ -488,7 +495,7 @@ export const buildCategorizeListFromObject = (
// Categorize's to field has two data sources, with edges as the data source.
// Changes in the edge or to field need to be synchronized to the form field.
return Object.keys(categorizeItem)
- .reduce>((pre, cur) => {
+ .reduce>>((pre, cur) => {
// synchronize edge data to the to field
pre.push({
diff --git a/web/src/pages/agents/agent-card.tsx b/web/src/pages/agents/agent-card.tsx
index 2ae1ab0c8..9c1de9d3a 100644
--- a/web/src/pages/agents/agent-card.tsx
+++ b/web/src/pages/agents/agent-card.tsx
@@ -14,7 +14,7 @@ export type DatasetCardProps = {
} & Pick, 'showAgentRenameModal'>;
export function AgentCard({ data, showAgentRenameModal }: DatasetCardProps) {
- const { navigateToAgent, navigateToDataflow } = useNavigatePage();
+ const { navigateToAgent } = useNavigatePage();
return (
{data.nickname}}
onClick={
- data.canvas_category === AgentCategory.DataflowCanvas
- ? navigateToDataflow(data.id)
- : navigateToAgent(data?.id)
+ // data.canvas_category === AgentCategory.DataflowCanvas
+ // ? navigateToDataflow(data.id)
+ // :
+ navigateToAgent(data?.id, data.canvas_category as AgentCategory)
}
icon={
data.canvas_category === AgentCategory.DataflowCanvas && (
diff --git a/web/src/pages/data-flow/canvas/node/begin-node.tsx b/web/src/pages/data-flow/canvas/node/begin-node.tsx
index 2d3db3cba..88b8cd870 100644
--- a/web/src/pages/data-flow/canvas/node/begin-node.tsx
+++ b/web/src/pages/data-flow/canvas/node/begin-node.tsx
@@ -1,26 +1,16 @@
import { IBeginNode } from '@/interfaces/database/flow';
-import { cn } from '@/lib/utils';
import { NodeProps, Position } from '@xyflow/react';
-import get from 'lodash/get';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
-import {
- BeginQueryType,
- BeginQueryTypeIconMap,
- NodeHandleId,
- Operator,
-} from '../../constant';
-import { BeginQuery } from '../../interface';
+import { NodeHandleId, Operator } from '../../constant';
import OperatorIcon from '../../operator-icon';
import { CommonHandle } from './handle';
import { RightHandleStyle } from './handle-icon';
-import styles from './index.less';
import { NodeWrapper } from './node-wrapper';
// TODO: do not allow other nodes to connect to this node
function InnerBeginNode({ data, id, selected }: NodeProps) {
const { t } = useTranslation();
- const inputs: Record = get(data, 'form.inputs', {});
return (
@@ -39,22 +29,6 @@ function InnerBeginNode({ data, id, selected }: NodeProps) {
{t(`dataflow.begin`)}
-
- {Object.entries(inputs).map(([key, val], idx) => {
- const Icon = BeginQueryTypeIconMap[val.type as BeginQueryType];
- return (
-
-
-
- {val.name}
- {val.optional ? 'Yes' : 'No'}
-
- );
- })}
-
);
}
diff --git a/web/src/pages/data-flow/constant.tsx b/web/src/pages/data-flow/constant.tsx
index c7b386b0b..e586cc1ec 100644
--- a/web/src/pages/data-flow/constant.tsx
+++ b/web/src/pages/data-flow/constant.tsx
@@ -3,24 +3,8 @@ import {
initialLlmBaseValues,
DataflowOperator as Operator,
} from '@/constants/agent';
-import {
- ChatVariableEnabledField,
- variableEnabledFieldMap,
-} from '@/constants/chat';
-import { setInitialChatVariableEnabledFieldValue } from '@/utils/chat';
export { DataflowOperator as Operator } from '@/constants/agent';
-import {
- Circle,
- CircleSlash2,
- CloudUpload,
- ListOrdered,
- OptionIcon,
- TextCursorInput,
- ToggleLeft,
- WrapText,
-} from 'lucide-react';
-
export enum FileType {
PDF = 'pdf',
Spreadsheet = 'spreadsheet',
@@ -104,47 +88,8 @@ export enum ContextGeneratorFieldName {
Metadata = 'metadata',
}
-export enum PromptRole {
- User = 'user',
- Assistant = 'assistant',
-}
-
-export enum AgentDialogueMode {
- Conversational = 'conversational',
- Task = 'task',
-}
-
export const BeginId = 'File';
-export const SwitchLogicOperatorOptions = ['and', 'or'];
-
-export const CommonOperatorList = Object.values(Operator).filter(
- (x) => x !== Operator.Note,
-);
-
-export const SwitchOperatorOptions = [
- { value: '=', label: 'equal', icon: 'equal' },
- { value: '≠', label: 'notEqual', icon: 'not-equals' },
- { value: '>', label: 'gt', icon: 'Less' },
- { value: '≥', label: 'ge', icon: 'Greater-or-equal' },
- { value: '<', label: 'lt', icon: 'Less' },
- { value: '≤', label: 'le', icon: 'less-or-equal' },
- { value: 'contains', label: 'contains', icon: 'Contains' },
- { value: 'not contains', label: 'notContains', icon: 'not-contains' },
- { value: 'start with', label: 'startWith', icon: 'list-start' },
- { value: 'end with', label: 'endWith', icon: 'list-end' },
- {
- value: 'empty',
- label: 'empty',
- icon: ,
- },
- {
- value: 'not empty',
- label: 'notEmpty',
- icon: ,
- },
-];
-
export const SwitchElseTo = 'end_cpn_ids';
export enum TokenizerSearchMethod {
@@ -186,15 +131,6 @@ export const initialBeginValues = {
},
};
-export const variableCheckBoxFieldMap = Object.keys(
- variableEnabledFieldMap,
-).reduce>((pre, cur) => {
- pre[cur] = setInitialChatVariableEnabledFieldValue(
- cur as ChatVariableEnabledField,
- );
- return pre;
-}, {});
-
export const initialNoteValues = {
text: '',
};
@@ -341,24 +277,6 @@ export const NodeMap = {
[Operator.Extractor]: 'contextNode',
};
-export enum BeginQueryType {
- Line = 'line',
- Paragraph = 'paragraph',
- Options = 'options',
- File = 'file',
- Integer = 'integer',
- Boolean = 'boolean',
-}
-
-export const BeginQueryTypeIconMap = {
- [BeginQueryType.Line]: TextCursorInput,
- [BeginQueryType.Paragraph]: WrapText,
- [BeginQueryType.Options]: OptionIcon,
- [BeginQueryType.File]: CloudUpload,
- [BeginQueryType.Integer]: ListOrdered,
- [BeginQueryType.Boolean]: ToggleLeft,
-};
-
export const NoDebugOperatorsList = [Operator.Begin];
export enum NodeHandleId {
@@ -370,17 +288,6 @@ export enum NodeHandleId {
AgentException = 'agentException',
}
-export enum VariableType {
- String = 'string',
- Array = 'array',
- File = 'file',
-}
-
-export enum AgentExceptionMethod {
- Comment = 'comment',
- Goto = 'goto',
-}
-
export const FileTypeSuffixMap = {
[FileType.PDF]: ['pdf'],
[FileType.Spreadsheet]: ['xls', 'xlsx', 'csv'],