diff --git a/web/src/i18n/en.ts b/web/src/i18n/en.ts
index 17fcde8d..9b957a84 100644
--- a/web/src/i18n/en.ts
+++ b/web/src/i18n/en.ts
@@ -2163,6 +2163,7 @@ Memory Bear: After the rebellion, regional warlordism intensified for several re
'memory-write': 'Memory Storage',
unknown: 'Unknown Node',
notes: 'Sticky Note',
+ 'document-extractor': 'Document Extractor',
clickToConfigure: 'Click to configure node parameters',
nodeProperties: 'Node Properties',
@@ -2361,6 +2362,9 @@ Memory Bear: After the rebellion, regional warlordism intensified for several re
placeholder: 'Enter note...',
removeLink: 'Remove Link',
},
+ 'document-extractor': {
+ file_selector: 'Input Variable',
+ },
name: 'Key',
type: 'Type',
value: 'Value',
diff --git a/web/src/i18n/zh.ts b/web/src/i18n/zh.ts
index d783bea3..862ed5d4 100644
--- a/web/src/i18n/zh.ts
+++ b/web/src/i18n/zh.ts
@@ -2160,6 +2160,7 @@ export const zh = {
'memory-write': '记忆储存',
unknown: '未知节点',
notes: '便签',
+ 'document-extractor': '文档提取器',
clickToConfigure: '点击配置节点参数',
nodeProperties: '节点属性',
@@ -2361,6 +2362,9 @@ export const zh = {
placeholder: '输入注释...',
removeLink: '取消链接',
},
+ 'document-extractor': {
+ file_selector: '输入变量',
+ },
name: '键',
type: '类型',
value: '值',
diff --git a/web/src/views/UserMemoryDetail/Neo4j.tsx b/web/src/views/UserMemoryDetail/Neo4j.tsx
index 1212a5c6..6dde8d69 100644
--- a/web/src/views/UserMemoryDetail/Neo4j.tsx
+++ b/web/src/views/UserMemoryDetail/Neo4j.tsx
@@ -161,10 +161,12 @@ const Neo4j: FC = () => {
-
-
-
-
+
e.stopPropagation()}>
+
+
+
+
+
)
}
diff --git a/web/src/views/Workflow/components/Editor/plugin/InitialValuePlugin.tsx b/web/src/views/Workflow/components/Editor/plugin/InitialValuePlugin.tsx
index 04e8ae1d..0ebcbe77 100644
--- a/web/src/views/Workflow/components/Editor/plugin/InitialValuePlugin.tsx
+++ b/web/src/views/Workflow/components/Editor/plugin/InitialValuePlugin.tsx
@@ -53,7 +53,7 @@ const InitialValuePlugin: React.FC = ({ value, options
const root = $getRoot();
root.clear();
- const parts = value.split(/(\{\{[^}]+\}\})/);
+ const parts = value.split(/(\{\{[^}]+\}\}|\n)/);
if (enableLineNumbers) {
const lines = value.split('\n');
@@ -63,8 +63,14 @@ const InitialValuePlugin: React.FC = ({ value, options
root.append(paragraph);
});
} else {
- const paragraph = $createParagraphNode();
+ let paragraph = $createParagraphNode();
+
parts.forEach(part => {
+ if (part === '\n') {
+ root.append(paragraph);
+ paragraph = $createParagraphNode();
+ return;
+ }
const match = part.match(/^\{\{([^.]+)\.([^}]+)\}\}$/);
const contextMatch = part.match(/^\{\{context\}\}$/);
const conversationMatch = part.match(/^\{\{conv\.([^}]+)\}\}$/);
@@ -78,10 +84,10 @@ const InitialValuePlugin: React.FC = ({ value, options
}
return
}
-
+
if (conversationMatch) {
const [_, variableName] = conversationMatch;
- const conversationSuggestion = optionsRef.current.find(s =>
+ const conversationSuggestion = optionsRef.current.find(s =>
s.group === 'CONVERSATION' && s.label === variableName
);
if (conversationSuggestion) {
@@ -91,7 +97,7 @@ const InitialValuePlugin: React.FC = ({ value, options
}
return
}
-
+
if (match) {
const [_, nodeId, label] = match;
diff --git a/web/src/views/Workflow/components/Properties/CycleVarsList/index.tsx b/web/src/views/Workflow/components/Properties/CycleVarsList/index.tsx
index 77ca0e61..09106a77 100644
--- a/web/src/views/Workflow/components/Properties/CycleVarsList/index.tsx
+++ b/web/src/views/Workflow/components/Properties/CycleVarsList/index.tsx
@@ -1,10 +1,11 @@
-import { type FC } from 'react'
+import { type FC, useMemo } from 'react'
import { useTranslation } from 'react-i18next';
import { Form, Select, Input, Button, InputNumber, Flex } from 'antd'
import VariableSelect from '../VariableSelect'
import type { Suggestion } from '../../Editor/plugin/AutocompletePlugin'
import RadioGroupBtn from '../RadioGroupBtn'
+import { getChildNodeVariables } from '../hooks/useVariableList'
interface CycleVar {
name: string;
@@ -44,40 +45,14 @@ const CycleVarsList: FC = ({
const { t } = useTranslation();
const form = Form.useFormInstance();
- // 获取循环节点的子节点变量
- const getChildNodeVariables = () => {
+ const availableOptions = useMemo(() => {
if (!selectedNode || !graphRef?.current || selectedNode.getData()?.type !== 'loop') {
return options;
}
+ const childVars = getChildNodeVariables(selectedNode, graphRef);
- const loopNodeId = selectedNode.getData()?.id;
- const childNodes = graphRef.current.getNodes().filter((node: any) =>
- node.getData()?.cycle === loopNodeId
- );
-
- const childVariables: Suggestion[] = [];
- childNodes.forEach((childNode: any) => {
- const childData = childNode.getData();
- if (childData?.config) {
- Object.keys(childData.config).forEach(key => {
- if (childData.config[key]?.defaultValue) {
- childVariables.push({
- key: `${childData.id}.${key}`,
- label: `${childData.name || childData.type}.${key}`,
- type: 'output',
- dataType: 'string',
- value: `${childData.id}.${key}`,
- nodeData: childData
- });
- }
- });
- }
- });
-
- return [...options, ...childVariables];
- };
-
- const availableOptions = getChildNodeVariables();
+ return options.filter(option => !childVars.some(item => item.value === option.value))
+ }, [options, selectedNode, graphRef]);
return (
diff --git a/web/src/views/Workflow/components/Properties/hooks/useVariableList.ts b/web/src/views/Workflow/components/Properties/hooks/useVariableList.ts
index 779174ff..dbda2759 100644
--- a/web/src/views/Workflow/components/Properties/hooks/useVariableList.ts
+++ b/web/src/views/Workflow/components/Properties/hooks/useVariableList.ts
@@ -42,6 +42,9 @@ const NODE_VARIABLES = {
'memory-read': [
{ label: 'answer', dataType: 'string', field: 'answer' },
{ label: 'intermediate_outputs', dataType: 'array[object]', field: 'intermediate_outputs' }
+ ],
+ 'document-extractor': [
+ { label: 'text', dataType: 'string', field: 'text' },
]
} as const;
@@ -177,7 +180,8 @@ const hasOutputNodeTypes = [
'var-aggregator',
'http-request',
'tool',
- 'jinja-render'
+ 'jinja-render',
+ 'document-extractor'
];
/**
diff --git a/web/src/views/Workflow/components/Properties/index.tsx b/web/src/views/Workflow/components/Properties/index.tsx
index 57ce2f38..bb80ed33 100644
--- a/web/src/views/Workflow/components/Properties/index.tsx
+++ b/web/src/views/Workflow/components/Properties/index.tsx
@@ -636,6 +636,8 @@ const Properties: FC = ({
size="small"
parentName={key}
options={getFilteredVariableList(selectedNode?.data?.type, key)}
+ selectedNode={selectedNode}
+ graphRef={graphRef}
/>
)
diff --git a/web/src/views/Workflow/constant.ts b/web/src/views/Workflow/constant.ts
index 6665bb86..cadff647 100644
--- a/web/src/views/Workflow/constant.ts
+++ b/web/src/views/Workflow/constant.ts
@@ -473,6 +473,16 @@ export const nodeLibrary: NodeLibrary[] = [
},
}
},
+ {
+ type: "document-extractor", icon: codeExecutionIcon,
+ config: {
+ file_selector: {
+ type: 'variableList',
+ placeholder: 'common.pleaseSelect',
+ onFilterVariableNames: ['sys.files']
+ }
+ }
+ },
]
},
];
@@ -858,100 +868,6 @@ export interface OutputVariable {
}>;
}
-/**
- * Output variable definitions for each node type
- * Specifies what variables each node produces
- */
-export const outputVariable: { [key: string]: OutputVariable } = {
- start: {
- sys: [
- { name: "message", type: "string" },
- { name: "conversation_id", type: "string" },
- { name: "execution_id", type: "string", },
- { name: "workspace_id", type: "string" },
- { name: "user_id", type: "string" },
- ],
- define: ['variables']
- },
- end: {
- },
- llm: {
- default: [
- { name: "output", type: "string" },
- ]
- },
- 'knowledge-retrieval': {
- default: [
- { name: "output", type: "array[object]" },
- ]
- },
- 'parameter-extractor': {
- default: [
- { name: "__is_success", type: "number" },
- { name: "__reason", type: "string" },
- ],
- define: ['params']
- },
- 'memory-read': {
- default: [
- { name: "answer", type: "string" },
- { name: "intermediate_outputs", type: "array[object]" },
- ],
- },
- 'memory-write': {
-
- },
- 'if-else': {
-
- },
- 'question-classifier': {
- default: [
- { name: "class_name", type: "string" },
- // { name: "output", type: "string" },
- ],
- },
- 'iteration': {
- default: [
- // { name: "item", type: "string" }, // 仅内部使用
- { name: "output", type: "array[string]" },
- ],
- },
- 'loop': {
- define: ['cycle_vars']
- },
- 'cycle-start': {
-
- },
- 'break': {
-
- },
- 'var-aggregator': {
- // default: [
- // { name: "output", type: "string" },
- // ],
- define: ['group_variables']
- },
- 'assigner': {
-
- },
- 'http-request': {
- default: [
- { name: "body", type: "string" },
- { name: "status_code", type: "number" },
- ],
- },
- 'tool': {
- default: [
- { name: "data", type: "string" },
- ],
- },
- 'jinja-render': {
- default: [
- { name: "output", type: "string" },
- ],
- },
-}
-
/**
* Default edge attributes configuration
* Defines visual styling for edges/connections