vectorvein 0.3.1__py3-none-any.whl → 0.3.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vectorvein/api/client.py +81 -103
- vectorvein/api/exceptions.py +1 -3
- vectorvein/api/models.py +11 -11
- vectorvein/chat_clients/anthropic_client.py +157 -169
- vectorvein/chat_clients/base_client.py +257 -198
- vectorvein/chat_clients/openai_compatible_client.py +150 -161
- vectorvein/chat_clients/utils.py +44 -24
- vectorvein/server/token_server.py +1 -1
- vectorvein/settings/__init__.py +27 -27
- vectorvein/types/defaults.py +32 -16
- vectorvein/types/llm_parameters.py +40 -34
- vectorvein/types/settings.py +10 -10
- vectorvein/utilities/media_processing.py +1 -1
- vectorvein/utilities/rate_limiter.py +5 -6
- vectorvein/utilities/retry.py +6 -5
- vectorvein/workflow/graph/edge.py +3 -3
- vectorvein/workflow/graph/node.py +14 -26
- vectorvein/workflow/graph/port.py +40 -39
- vectorvein/workflow/graph/workflow.py +13 -25
- vectorvein/workflow/nodes/audio_generation.py +5 -7
- vectorvein/workflow/nodes/control_flows.py +7 -9
- vectorvein/workflow/nodes/file_processing.py +4 -6
- vectorvein/workflow/nodes/image_generation.py +20 -22
- vectorvein/workflow/nodes/llms.py +13 -15
- vectorvein/workflow/nodes/media_editing.py +26 -40
- vectorvein/workflow/nodes/media_processing.py +19 -21
- vectorvein/workflow/nodes/output.py +10 -12
- vectorvein/workflow/nodes/relational_db.py +3 -5
- vectorvein/workflow/nodes/text_processing.py +8 -10
- vectorvein/workflow/nodes/tools.py +8 -10
- vectorvein/workflow/nodes/triggers.py +1 -3
- vectorvein/workflow/nodes/vector_db.py +3 -5
- vectorvein/workflow/nodes/video_generation.py +4 -6
- vectorvein/workflow/nodes/web_crawlers.py +4 -6
- vectorvein/workflow/utils/analyse.py +5 -13
- vectorvein/workflow/utils/check.py +6 -16
- vectorvein/workflow/utils/json_to_code.py +6 -14
- vectorvein/workflow/utils/layout.py +3 -5
- {vectorvein-0.3.1.dist-info → vectorvein-0.3.3.dist-info}/METADATA +1 -1
- vectorvein-0.3.3.dist-info/RECORD +68 -0
- {vectorvein-0.3.1.dist-info → vectorvein-0.3.3.dist-info}/WHEEL +1 -1
- vectorvein-0.3.1.dist-info/RECORD +0 -68
- {vectorvein-0.3.1.dist-info → vectorvein-0.3.3.dist-info}/entry_points.txt +0 -0
@@ -1,5 +1,5 @@
|
|
1
1
|
import uuid
|
2
|
-
from typing import
|
2
|
+
from typing import Any, TYPE_CHECKING
|
3
3
|
|
4
4
|
from .port import InputPort, OutputPort
|
5
5
|
|
@@ -8,7 +8,7 @@ if TYPE_CHECKING:
|
|
8
8
|
from .port import PortType, Port
|
9
9
|
|
10
10
|
|
11
|
-
class PortsDict(
|
11
|
+
class PortsDict(dict[str, "Port"]):
|
12
12
|
"""自定义字典类,用于管理节点的端口,并强制执行端口添加权限。"""
|
13
13
|
|
14
14
|
def __init__(self, owner_node: "Node", *args, **kwargs):
|
@@ -22,13 +22,9 @@ class PortsDict(Dict[str, "Port"]):
|
|
22
22
|
return
|
23
23
|
|
24
24
|
if isinstance(value, OutputPort) and not self._owner_node.can_add_output_ports:
|
25
|
-
raise ValueError(
|
26
|
-
f"Node<{self._owner_node.id}> '{self._owner_node.type}' does not allow adding output ports"
|
27
|
-
)
|
25
|
+
raise ValueError(f"Node<{self._owner_node.id}> '{self._owner_node.type}' does not allow adding output ports")
|
28
26
|
elif isinstance(value, InputPort) and not self._owner_node.can_add_input_ports:
|
29
|
-
raise ValueError(
|
30
|
-
f"Node<{self._owner_node.id}> '{self._owner_node.type}' does not allow adding input ports"
|
31
|
-
)
|
27
|
+
raise ValueError(f"Node<{self._owner_node.id}> '{self._owner_node.type}' does not allow adding input ports")
|
32
28
|
|
33
29
|
super().__setitem__(key, value)
|
34
30
|
|
@@ -44,9 +40,9 @@ class Node:
|
|
44
40
|
category: str,
|
45
41
|
task_name: str,
|
46
42
|
description: str = "",
|
47
|
-
ports:
|
48
|
-
node_id:
|
49
|
-
position:
|
43
|
+
ports: dict[str, "Port"] | None = None,
|
44
|
+
node_id: str | None = None,
|
45
|
+
position: dict[str, float] | None = None,
|
50
46
|
seleted_workflow_title: str = "",
|
51
47
|
is_template: bool = False,
|
52
48
|
initialized: bool = False,
|
@@ -67,7 +63,7 @@ class Node:
|
|
67
63
|
self.ports[name] = port
|
68
64
|
self.ports.finish_initialization()
|
69
65
|
|
70
|
-
self.position:
|
66
|
+
self.position: dict[str, float] = position or {"x": 0, "y": 0}
|
71
67
|
self.seleted_workflow_title: str = seleted_workflow_title
|
72
68
|
self.is_template: bool = is_template
|
73
69
|
self.initialized: bool = initialized
|
@@ -78,10 +74,10 @@ class Node:
|
|
78
74
|
def add_port(
|
79
75
|
self,
|
80
76
|
name: str,
|
81
|
-
port_type:
|
77
|
+
port_type: "PortType | str",
|
82
78
|
show: bool = False,
|
83
79
|
value: Any = None,
|
84
|
-
options:
|
80
|
+
options: list[Any] | None = None,
|
85
81
|
is_output: bool = False,
|
86
82
|
**kwargs,
|
87
83
|
):
|
@@ -91,20 +87,16 @@ class Node:
|
|
91
87
|
|
92
88
|
if self.has_port(name):
|
93
89
|
raise ValueError(f"Node<{self.id}> '{self.type}' already has a port named '{name}'")
|
94
|
-
self.ports[name] = OutputPort(
|
95
|
-
name=name, port_type=port_type, show=show, value=value, options=options, **kwargs
|
96
|
-
)
|
90
|
+
self.ports[name] = OutputPort(name=name, port_type=port_type, show=show, value=value, options=options, **kwargs)
|
97
91
|
else:
|
98
92
|
if not self.can_add_input_ports:
|
99
93
|
raise ValueError(f"Node<{self.id}> '{self.type}' does not allow adding input ports")
|
100
94
|
|
101
95
|
if self.has_port(name):
|
102
96
|
raise ValueError(f"Node<{self.id}> '{self.type}' already has a port named '{name}'")
|
103
|
-
self.ports[name] = InputPort(
|
104
|
-
name=name, port_type=port_type, show=show, value=value, options=options, **kwargs
|
105
|
-
)
|
97
|
+
self.ports[name] = InputPort(name=name, port_type=port_type, show=show, value=value, options=options, **kwargs)
|
106
98
|
|
107
|
-
def to_dict(self) ->
|
99
|
+
def to_dict(self) -> dict[str, Any]:
|
108
100
|
# 如果端口有条件表达式,且根据条件不能显示,则端口 show 要强制设置为 False
|
109
101
|
for port in self.ports.values():
|
110
102
|
port_show = port.show
|
@@ -121,11 +113,7 @@ class Node:
|
|
121
113
|
"description": self.description,
|
122
114
|
"seleted_workflow_title": self.seleted_workflow_title,
|
123
115
|
"is_template": self.is_template,
|
124
|
-
"template": {
|
125
|
-
port_name: port.to_dict()
|
126
|
-
for port_name, port in self.ports.items()
|
127
|
-
if port_name not in ["debug", "seleted_workflow_title", "is_template"]
|
128
|
-
},
|
116
|
+
"template": {port_name: port.to_dict() for port_name, port in self.ports.items() if port_name not in ["debug", "seleted_workflow_title", "is_template"]},
|
129
117
|
},
|
130
118
|
"category": self.category,
|
131
119
|
"position": self.position,
|
@@ -1,5 +1,6 @@
|
|
1
1
|
from enum import Enum
|
2
|
-
from typing import
|
2
|
+
from typing import Any
|
3
|
+
from collections.abc import Callable
|
3
4
|
|
4
5
|
|
5
6
|
class PortType(Enum):
|
@@ -20,24 +21,24 @@ class Port:
|
|
20
21
|
def __init__(
|
21
22
|
self,
|
22
23
|
name: str,
|
23
|
-
port_type:
|
24
|
+
port_type: "PortType | str",
|
24
25
|
required: bool = True,
|
25
26
|
show: bool = False,
|
26
27
|
value: Any = None,
|
27
|
-
options:
|
28
|
-
field_type:
|
28
|
+
options: list[Any] | None = None,
|
29
|
+
field_type: str | None = None,
|
29
30
|
is_output: bool = False,
|
30
|
-
condition:
|
31
|
-
condition_python:
|
32
|
-
max_length:
|
33
|
-
support_file_types:
|
34
|
-
multiple:
|
35
|
-
group:
|
31
|
+
condition: str | None = None,
|
32
|
+
condition_python: Callable[[dict[str, "Port"]], bool] | None = None,
|
33
|
+
max_length: int | None = None,
|
34
|
+
support_file_types: list[str] | None = None,
|
35
|
+
multiple: bool | None = None,
|
36
|
+
group: str | None = None,
|
36
37
|
group_collpased: bool = False,
|
37
38
|
has_tooltip: bool = False,
|
38
|
-
max:
|
39
|
-
min:
|
40
|
-
max_count:
|
39
|
+
max: int | float | None = None,
|
40
|
+
min: int | float | None = None,
|
41
|
+
max_count: int | None = None,
|
41
42
|
list: bool = False,
|
42
43
|
) -> None:
|
43
44
|
self.name = name
|
@@ -72,7 +73,7 @@ class Port:
|
|
72
73
|
else:
|
73
74
|
return "str"
|
74
75
|
|
75
|
-
def to_dict(self) ->
|
76
|
+
def to_dict(self) -> dict[str, Any]:
|
76
77
|
return {
|
77
78
|
"name": self.name,
|
78
79
|
"display_name": self.name,
|
@@ -102,7 +103,7 @@ class Port:
|
|
102
103
|
@value.setter
|
103
104
|
def value(self, value: Any) -> None:
|
104
105
|
if self.options:
|
105
|
-
if value not in
|
106
|
+
if value not in (x["value"] for x in self.options):
|
106
107
|
raise ValueError(f"Value `{value}` is not in Port `{self.name}` options {self.options}")
|
107
108
|
self._value = value
|
108
109
|
|
@@ -117,23 +118,23 @@ class InputPort(Port):
|
|
117
118
|
def __init__(
|
118
119
|
self,
|
119
120
|
name: str,
|
120
|
-
port_type:
|
121
|
+
port_type: PortType | str,
|
121
122
|
required: bool = True,
|
122
123
|
show: bool = False,
|
123
124
|
value: Any = None,
|
124
|
-
options:
|
125
|
-
field_type:
|
126
|
-
condition:
|
127
|
-
condition_python:
|
128
|
-
max_length:
|
129
|
-
support_file_types:
|
130
|
-
multiple:
|
131
|
-
group:
|
125
|
+
options: list[Any] | None = None,
|
126
|
+
field_type: str | None = None,
|
127
|
+
condition: str | None = None,
|
128
|
+
condition_python: Callable[[dict[str, "Port"]], bool] | None = None,
|
129
|
+
max_length: int | None = None,
|
130
|
+
support_file_types: list[str] | None = None,
|
131
|
+
multiple: bool | None = None,
|
132
|
+
group: str | None = None,
|
132
133
|
group_collpased: bool = False,
|
133
134
|
has_tooltip: bool = False,
|
134
|
-
max:
|
135
|
-
min:
|
136
|
-
max_count:
|
135
|
+
max: int | float | None = None,
|
136
|
+
min: int | float | None = None,
|
137
|
+
max_count: int | None = None,
|
137
138
|
list: bool = False,
|
138
139
|
) -> None:
|
139
140
|
super().__init__(
|
@@ -164,23 +165,23 @@ class OutputPort(Port):
|
|
164
165
|
def __init__(
|
165
166
|
self,
|
166
167
|
name: str = "output",
|
167
|
-
port_type:
|
168
|
+
port_type: PortType | str = PortType.TEXT,
|
168
169
|
required: bool = False,
|
169
170
|
show: bool = False,
|
170
171
|
value: Any = None,
|
171
|
-
options:
|
172
|
-
field_type:
|
173
|
-
condition:
|
174
|
-
condition_python:
|
175
|
-
max_length:
|
176
|
-
support_file_types:
|
177
|
-
multiple:
|
178
|
-
group:
|
172
|
+
options: list[Any] | None = None,
|
173
|
+
field_type: str | None = None,
|
174
|
+
condition: str | None = None,
|
175
|
+
condition_python: Callable[[dict[str, "Port"]], bool] | None = None,
|
176
|
+
max_length: int | None = None,
|
177
|
+
support_file_types: list[str] | None = None,
|
178
|
+
multiple: bool | None = None,
|
179
|
+
group: str | None = None,
|
179
180
|
group_collpased: bool = False,
|
180
181
|
has_tooltip: bool = False,
|
181
|
-
max:
|
182
|
-
min:
|
183
|
-
max_count:
|
182
|
+
max: int | float | None = None,
|
183
|
+
min: int | float | None = None,
|
184
|
+
max_count: int | None = None,
|
184
185
|
list: bool = False,
|
185
186
|
) -> None:
|
186
187
|
super().__init__(
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import json
|
2
|
-
from typing import
|
2
|
+
from typing import Any
|
3
3
|
|
4
4
|
from .node import Node
|
5
5
|
from .edge import Edge
|
@@ -18,13 +18,13 @@ from ..utils.check import (
|
|
18
18
|
|
19
19
|
class Workflow:
|
20
20
|
def __init__(self) -> None:
|
21
|
-
self.nodes:
|
22
|
-
self.edges:
|
21
|
+
self.nodes: list[Node] = []
|
22
|
+
self.edges: list[Edge] = []
|
23
23
|
|
24
24
|
def add_node(self, node: Node):
|
25
25
|
self.nodes.append(node)
|
26
26
|
|
27
|
-
def add_nodes(self, nodes:
|
27
|
+
def add_nodes(self, nodes: list[Node]):
|
28
28
|
self.nodes.extend(nodes)
|
29
29
|
|
30
30
|
def add_edge(self, edge: Edge):
|
@@ -32,9 +32,9 @@ class Workflow:
|
|
32
32
|
|
33
33
|
def connect(
|
34
34
|
self,
|
35
|
-
source_node:
|
35
|
+
source_node: str | Node,
|
36
36
|
source_port: str,
|
37
|
-
target_node:
|
37
|
+
target_node: str | Node,
|
38
38
|
target_port: str,
|
39
39
|
):
|
40
40
|
# 获取源节点ID
|
@@ -72,9 +72,7 @@ class Workflow:
|
|
72
72
|
# 确保目标端口是InputPort而不是OutputPort
|
73
73
|
target_port_obj = target_node_obj.ports[target_port]
|
74
74
|
if isinstance(target_port_obj, OutputPort):
|
75
|
-
raise ValueError(
|
76
|
-
f"The target port {target_port} of node {target_node_id} is an output port. OutputPort cannot be a connection target."
|
77
|
-
)
|
75
|
+
raise ValueError(f"The target port {target_port} of node {target_node_id} is an output port. OutputPort cannot be a connection target.")
|
78
76
|
|
79
77
|
# 检查目标端口是否已有被连接的线
|
80
78
|
for edge in self.edges:
|
@@ -161,7 +159,7 @@ class Workflow:
|
|
161
159
|
|
162
160
|
return result
|
163
161
|
|
164
|
-
def layout(self, options:
|
162
|
+
def layout(self, options: dict[str, Any] | None = None) -> "Workflow":
|
165
163
|
"""对工作流中的节点进行自动布局,计算并更新每个节点的位置。
|
166
164
|
|
167
165
|
此方法实现了一个简单的分层布局算法,将节点按照有向图的拓扑结构进行排列。
|
@@ -222,9 +220,7 @@ class Workflow:
|
|
222
220
|
node_type=node_type,
|
223
221
|
category=category,
|
224
222
|
task_name=task_name,
|
225
|
-
description=node_data["data"].get(
|
226
|
-
"description", node_instance.description if hasattr(node_instance, "description") else ""
|
227
|
-
),
|
223
|
+
description=node_data["data"].get("description", node_instance.description if hasattr(node_instance, "description") else ""),
|
228
224
|
node_id=node_data["id"],
|
229
225
|
position=node_data.get("position", {"x": 0, "y": 0}),
|
230
226
|
seleted_workflow_title=node_data["data"].get("seleted_workflow_title", ""),
|
@@ -278,9 +274,7 @@ class Workflow:
|
|
278
274
|
is_output = port_data.get("is_output", False)
|
279
275
|
|
280
276
|
# 检查节点是否允许添加该类型的端口
|
281
|
-
if (is_output and not node.can_add_output_ports) or (
|
282
|
-
not is_output and not node.can_add_input_ports
|
283
|
-
):
|
277
|
+
if (is_output and not node.can_add_output_ports) or (not is_output and not node.can_add_input_ports):
|
284
278
|
# 如果不允许添加,跳过该端口
|
285
279
|
continue
|
286
280
|
|
@@ -295,9 +289,7 @@ class Workflow:
|
|
295
289
|
options=port_data.get("options"),
|
296
290
|
field_type=port_data.get("type"),
|
297
291
|
max_length=port_data.get("max_length"),
|
298
|
-
support_file_types=port_data.get("support_file_types", "").split(", ")
|
299
|
-
if port_data.get("support_file_types")
|
300
|
-
else None,
|
292
|
+
support_file_types=port_data.get("support_file_types", "").split(", ") if port_data.get("support_file_types") else None,
|
301
293
|
multiple=port_data.get("multiple"),
|
302
294
|
group=port_data.get("group"),
|
303
295
|
group_collpased=port_data.get("group_collpased", False),
|
@@ -316,9 +308,7 @@ class Workflow:
|
|
316
308
|
options=port_data.get("options"),
|
317
309
|
field_type=port_data.get("type"),
|
318
310
|
max_length=port_data.get("max_length"),
|
319
|
-
support_file_types=port_data.get("support_file_types", "").split(", ")
|
320
|
-
if port_data.get("support_file_types")
|
321
|
-
else None,
|
311
|
+
support_file_types=port_data.get("support_file_types", "").split(", ") if port_data.get("support_file_types") else None,
|
322
312
|
multiple=port_data.get("multiple"),
|
323
313
|
group=port_data.get("group"),
|
324
314
|
group_collpased=port_data.get("group_collpased", False),
|
@@ -348,9 +338,7 @@ class Workflow:
|
|
348
338
|
if target_node.has_port(target_port_name):
|
349
339
|
target_port = target_node.ports[target_port_name]
|
350
340
|
if isinstance(target_port, OutputPort):
|
351
|
-
raise ValueError(
|
352
|
-
f"The target port {target_port_name} of node {target_node_id} is an output port. OutputPort cannot be a connection target."
|
353
|
-
)
|
341
|
+
raise ValueError(f"The target port {target_port_name} of node {target_node_id} is an output port. OutputPort cannot be a connection target.")
|
354
342
|
|
355
343
|
edge = Edge(
|
356
344
|
id=edge_data["id"],
|
@@ -1,11 +1,9 @@
|
|
1
|
-
from typing import Optional
|
2
|
-
|
3
1
|
from ..graph.node import Node
|
4
2
|
from ..graph.port import PortType, InputPort, OutputPort
|
5
3
|
|
6
4
|
|
7
5
|
class MinimaxMusicGeneration(Node):
|
8
|
-
def __init__(self, id:
|
6
|
+
def __init__(self, id: str | None = None):
|
9
7
|
super().__init__(
|
10
8
|
node_type="MinimaxMusicGeneration",
|
11
9
|
category="audio_generation",
|
@@ -15,7 +13,7 @@ class MinimaxMusicGeneration(Node):
|
|
15
13
|
"audio_file": InputPort(
|
16
14
|
name="audio_file",
|
17
15
|
port_type=PortType.FILE,
|
18
|
-
value=
|
16
|
+
value=[],
|
19
17
|
support_file_types=[".wav", ".mp3"],
|
20
18
|
multiple=True,
|
21
19
|
),
|
@@ -88,7 +86,7 @@ class MinimaxMusicGeneration(Node):
|
|
88
86
|
|
89
87
|
|
90
88
|
class SoundEffects(Node):
|
91
|
-
def __init__(self, id:
|
89
|
+
def __init__(self, id: str | None = None):
|
92
90
|
super().__init__(
|
93
91
|
node_type="SoundEffects",
|
94
92
|
category="audio_generation",
|
@@ -105,7 +103,7 @@ class SoundEffects(Node):
|
|
105
103
|
"video": InputPort(
|
106
104
|
name="video",
|
107
105
|
port_type=PortType.FILE,
|
108
|
-
value=
|
106
|
+
value=[],
|
109
107
|
support_file_types=[".mp4", ".mov", ".webm", ".m4v", ".gif"],
|
110
108
|
multiple=True,
|
111
109
|
),
|
@@ -131,7 +129,7 @@ class SoundEffects(Node):
|
|
131
129
|
|
132
130
|
|
133
131
|
class Tts(Node):
|
134
|
-
def __init__(self, id:
|
132
|
+
def __init__(self, id: str | None = None):
|
135
133
|
super().__init__(
|
136
134
|
node_type="Tts",
|
137
135
|
category="audio_generation",
|
@@ -1,11 +1,9 @@
|
|
1
|
-
from typing import Optional
|
2
|
-
|
3
1
|
from ..graph.node import Node
|
4
2
|
from ..graph.port import PortType, InputPort, OutputPort
|
5
3
|
|
6
4
|
|
7
5
|
class Conditional(Node):
|
8
|
-
def __init__(self, id:
|
6
|
+
def __init__(self, id: str | None = None):
|
9
7
|
super().__init__(
|
10
8
|
node_type="Conditional",
|
11
9
|
category="control_flows",
|
@@ -66,7 +64,7 @@ class Conditional(Node):
|
|
66
64
|
|
67
65
|
|
68
66
|
class Empty(Node):
|
69
|
-
def __init__(self, id:
|
67
|
+
def __init__(self, id: str | None = None):
|
70
68
|
super().__init__(
|
71
69
|
node_type="Empty",
|
72
70
|
category="control_flows",
|
@@ -84,7 +82,7 @@ class Empty(Node):
|
|
84
82
|
|
85
83
|
|
86
84
|
class HumanFeedback(Node):
|
87
|
-
def __init__(self, id:
|
85
|
+
def __init__(self, id: str | None = None):
|
88
86
|
super().__init__(
|
89
87
|
node_type="HumanFeedback",
|
90
88
|
category="control_flows",
|
@@ -107,7 +105,7 @@ class HumanFeedback(Node):
|
|
107
105
|
|
108
106
|
|
109
107
|
class JsonProcess(Node):
|
110
|
-
def __init__(self, id:
|
108
|
+
def __init__(self, id: str | None = None):
|
111
109
|
super().__init__(
|
112
110
|
node_type="JsonProcess",
|
113
111
|
category="control_flows",
|
@@ -140,7 +138,7 @@ class JsonProcess(Node):
|
|
140
138
|
"keys": InputPort(
|
141
139
|
name="keys",
|
142
140
|
port_type=PortType.INPUT,
|
143
|
-
value=
|
141
|
+
value=[],
|
144
142
|
),
|
145
143
|
"default_value": InputPort(
|
146
144
|
name="default_value",
|
@@ -156,7 +154,7 @@ class JsonProcess(Node):
|
|
156
154
|
|
157
155
|
|
158
156
|
class RandomChoice(Node):
|
159
|
-
def __init__(self, id:
|
157
|
+
def __init__(self, id: str | None = None):
|
160
158
|
super().__init__(
|
161
159
|
node_type="RandomChoice",
|
162
160
|
category="control_flows",
|
@@ -166,7 +164,7 @@ class RandomChoice(Node):
|
|
166
164
|
"input": InputPort(
|
167
165
|
name="input",
|
168
166
|
port_type=PortType.LIST,
|
169
|
-
value=
|
167
|
+
value=[],
|
170
168
|
),
|
171
169
|
"output": OutputPort(),
|
172
170
|
},
|
@@ -1,11 +1,9 @@
|
|
1
|
-
from typing import Optional
|
2
|
-
|
3
1
|
from ..graph.node import Node
|
4
2
|
from ..graph.port import PortType, InputPort, OutputPort
|
5
3
|
|
6
4
|
|
7
5
|
class FileLoader(Node):
|
8
|
-
def __init__(self, id:
|
6
|
+
def __init__(self, id: str | None = None):
|
9
7
|
super().__init__(
|
10
8
|
node_type="FileLoader",
|
11
9
|
category="file_processing",
|
@@ -15,7 +13,7 @@ class FileLoader(Node):
|
|
15
13
|
"files": InputPort(
|
16
14
|
name="files",
|
17
15
|
port_type=PortType.FILE,
|
18
|
-
value=
|
16
|
+
value=[],
|
19
17
|
multiple=True,
|
20
18
|
show=True,
|
21
19
|
),
|
@@ -67,7 +65,7 @@ class FileLoader(Node):
|
|
67
65
|
|
68
66
|
|
69
67
|
class FileUpload(Node):
|
70
|
-
def __init__(self, id:
|
68
|
+
def __init__(self, id: str | None = None):
|
71
69
|
super().__init__(
|
72
70
|
node_type="FileUpload",
|
73
71
|
category="file_processing",
|
@@ -77,7 +75,7 @@ class FileUpload(Node):
|
|
77
75
|
"files": InputPort(
|
78
76
|
name="files",
|
79
77
|
port_type=PortType.FILE,
|
80
|
-
value=
|
78
|
+
value=[],
|
81
79
|
support_file_types=["*/*"],
|
82
80
|
multiple=True,
|
83
81
|
show=True,
|