vellum-ai 0.13.8__py3-none-any.whl → 0.13.10__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.
- vellum/client/core/client_wrapper.py +1 -1
- vellum/plugins/vellum_mypy.py +6 -2
- vellum/workflows/descriptors/utils.py +1 -1
- vellum/workflows/nodes/bases/base.py +1 -2
- vellum/workflows/nodes/displayable/api_node/node.py +4 -1
- vellum/workflows/nodes/displayable/bases/api_node/node.py +4 -1
- vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py +4 -1
- vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py +4 -0
- vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +4 -0
- vellum/workflows/nodes/displayable/bases/search_node.py +4 -0
- vellum/workflows/nodes/displayable/code_execution_node/node.py +4 -1
- vellum/workflows/nodes/displayable/conditional_node/node.py +4 -0
- vellum/workflows/nodes/displayable/final_output_node/node.py +4 -0
- vellum/workflows/nodes/displayable/guardrail_node/node.py +4 -1
- vellum/workflows/nodes/displayable/inline_prompt_node/node.py +4 -0
- vellum/workflows/nodes/displayable/merge_node/node.py +3 -1
- vellum/workflows/nodes/displayable/note_node/node.py +4 -0
- vellum/workflows/nodes/displayable/prompt_deployment_node/node.py +4 -0
- vellum/workflows/nodes/displayable/search_node/node.py +4 -0
- vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +4 -1
- vellum/workflows/nodes/utils.py +6 -18
- {vellum_ai-0.13.8.dist-info → vellum_ai-0.13.10.dist-info}/METADATA +1 -1
- {vellum_ai-0.13.8.dist-info → vellum_ai-0.13.10.dist-info}/RECORD +49 -48
- vellum_ee/workflows/display/nodes/base_node_display.py +103 -3
- vellum_ee/workflows/display/nodes/vellum/base_node.py +34 -105
- vellum_ee/workflows/display/nodes/vellum/conditional_node.py +2 -1
- vellum_ee/workflows/display/nodes/vellum/tests/test_try_node.py +63 -0
- vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py +3 -4
- vellum_ee/workflows/display/nodes/vellum/try_node.py +28 -4
- vellum_ee/workflows/display/nodes/vellum/utils.py +1 -80
- vellum_ee/workflows/display/tests/test_vellum_workflow_display.py +56 -0
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py +3 -2
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +143 -26
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +10 -10
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py +6 -6
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py +32 -34
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py +4 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +1 -2
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +5 -5
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py +1 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +6 -3
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +6 -3
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +3 -3
- vellum_ee/workflows/display/utils/vellum.py +74 -4
- vellum_ee/workflows/display/workflows/base_workflow_display.py +22 -24
- vellum_ee/workflows/display/workflows/vellum_workflow_display.py +6 -15
- {vellum_ai-0.13.8.dist-info → vellum_ai-0.13.10.dist-info}/LICENSE +0 -0
- {vellum_ai-0.13.8.dist-info → vellum_ai-0.13.10.dist-info}/WHEEL +0 -0
- {vellum_ai-0.13.8.dist-info → vellum_ai-0.13.10.dist-info}/entry_points.txt +0 -0
@@ -1,13 +1,12 @@
|
|
1
1
|
import pytest
|
2
2
|
from uuid import UUID, uuid4
|
3
|
-
from typing import List
|
3
|
+
from typing import List
|
4
4
|
|
5
5
|
from vellum.client.types.string_vellum_value import StringVellumValue
|
6
6
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
7
7
|
from vellum.workflows.inputs import BaseInputs
|
8
8
|
from vellum.workflows.nodes.bases import BaseNode
|
9
9
|
from vellum.workflows.outputs import BaseOutputs
|
10
|
-
from vellum.workflows.references import OutputReference, WorkflowInputReference
|
11
10
|
from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
|
12
11
|
from vellum_ee.workflows.display.nodes.types import NodeOutputDisplay
|
13
12
|
from vellum_ee.workflows.display.nodes.vellum.utils import create_node_input_value_pointer_rules
|
@@ -92,12 +91,12 @@ def test_create_node_input_value_pointer_rules(
|
|
92
91
|
entrypoint_node_display=NodeDisplayData(),
|
93
92
|
),
|
94
93
|
global_workflow_input_displays={
|
95
|
-
|
94
|
+
Inputs.example_workflow_input: WorkflowInputsVellumDisplayOverrides(
|
96
95
|
id=UUID("a154c29d-fac0-4cd0-ba88-bc52034f5470"),
|
97
96
|
),
|
98
97
|
},
|
99
98
|
global_node_output_displays={
|
100
|
-
|
99
|
+
MyNodeA.Outputs.output: (
|
101
100
|
MyNodeA,
|
102
101
|
NodeOutputDisplay(id=UUID("4b16a629-11a1-4b3f-a965-a57b872d13b8"), name="output"),
|
103
102
|
),
|
@@ -1,16 +1,19 @@
|
|
1
1
|
from uuid import UUID
|
2
|
-
from typing import Any, Callable, ClassVar, Generic, Optional, Type, TypeVar, cast
|
2
|
+
from typing import Any, Callable, ClassVar, Generic, Optional, Tuple, Type, TypeVar, cast
|
3
3
|
|
4
4
|
from vellum.workflows.nodes.bases.base import BaseNode
|
5
5
|
from vellum.workflows.nodes.core.try_node.node import TryNode
|
6
6
|
from vellum.workflows.nodes.utils import ADORNMENT_MODULE_NAME, get_wrapped_node
|
7
|
+
from vellum.workflows.references.output import OutputReference
|
7
8
|
from vellum.workflows.types.core import JsonObject
|
8
9
|
from vellum.workflows.types.utils import get_original_base
|
9
10
|
from vellum.workflows.utils.uuids import uuid4_from_hash
|
10
11
|
from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
|
11
12
|
from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
|
12
13
|
from vellum_ee.workflows.display.nodes.get_node_display_class import get_node_display_class
|
14
|
+
from vellum_ee.workflows.display.nodes.types import NodeOutputDisplay
|
13
15
|
from vellum_ee.workflows.display.nodes.utils import raise_if_descriptor
|
16
|
+
from vellum_ee.workflows.display.nodes.vellum.base_node import BaseNodeDisplay as GenericBaseNodeDisplay
|
14
17
|
from vellum_ee.workflows.display.types import WorkflowDisplayContext
|
15
18
|
|
16
19
|
_TryNodeType = TypeVar("_TryNodeType", bound=TryNode)
|
@@ -22,9 +25,8 @@ class BaseTryNodeDisplay(BaseNodeVellumDisplay[_TryNodeType], Generic[_TryNodeTy
|
|
22
25
|
def serialize(self, display_context: WorkflowDisplayContext, **kwargs: Any) -> JsonObject:
|
23
26
|
node = self._node
|
24
27
|
|
25
|
-
|
26
|
-
|
27
|
-
except AttributeError:
|
28
|
+
inner_node = get_wrapped_node(node)
|
29
|
+
if not inner_node:
|
28
30
|
subworkflow = raise_if_descriptor(node.subworkflow)
|
29
31
|
if not isinstance(subworkflow.graph, type) or not issubclass(subworkflow.graph, BaseNode):
|
30
32
|
raise NotImplementedError(
|
@@ -32,6 +34,12 @@ class BaseTryNodeDisplay(BaseNodeVellumDisplay[_TryNodeType], Generic[_TryNodeTy
|
|
32
34
|
)
|
33
35
|
|
34
36
|
inner_node = subworkflow.graph
|
37
|
+
elif inner_node.__bases__[0] is BaseNode:
|
38
|
+
# If the wrapped node is a generic node, we let generic node do adornment handling
|
39
|
+
class TryBaseNodeDisplay(GenericBaseNodeDisplay[node]): # type: ignore[valid-type]
|
40
|
+
pass
|
41
|
+
|
42
|
+
return TryBaseNodeDisplay().serialize(display_context)
|
35
43
|
|
36
44
|
# We need the node display class of the underlying node because
|
37
45
|
# it contains the logic for serializing the node and potential display overrides
|
@@ -57,6 +65,22 @@ class BaseTryNodeDisplay(BaseNodeVellumDisplay[_TryNodeType], Generic[_TryNodeTy
|
|
57
65
|
|
58
66
|
return serialized_node
|
59
67
|
|
68
|
+
def get_node_output_display(self, output: OutputReference) -> Tuple[Type[BaseNode], NodeOutputDisplay]:
|
69
|
+
inner_node = self._node.__wrapped_node__
|
70
|
+
if not inner_node:
|
71
|
+
return super().get_node_output_display(output)
|
72
|
+
|
73
|
+
node_display_class = get_node_display_class(BaseNodeVellumDisplay, inner_node)
|
74
|
+
node_display = node_display_class()
|
75
|
+
if output.name == "error":
|
76
|
+
return inner_node, NodeOutputDisplay(
|
77
|
+
id=self.error_output_id or uuid4_from_hash(f"{node_display.node_id}|error_output_id"),
|
78
|
+
name="error",
|
79
|
+
)
|
80
|
+
|
81
|
+
inner_output = getattr(inner_node.Outputs, output.name)
|
82
|
+
return node_display.get_node_output_display(inner_output)
|
83
|
+
|
60
84
|
@classmethod
|
61
85
|
def wrap(cls, error_output_id: Optional[UUID] = None) -> Callable[..., Type["BaseTryNodeDisplay"]]:
|
62
86
|
_error_output_id = error_output_id
|
@@ -2,34 +2,9 @@ from uuid import UUID
|
|
2
2
|
from typing import Any, List, Optional, Type, Union, cast
|
3
3
|
|
4
4
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
5
|
-
from vellum.workflows.expressions.and_ import AndExpression
|
6
|
-
from vellum.workflows.expressions.begins_with import BeginsWithExpression
|
7
|
-
from vellum.workflows.expressions.between import BetweenExpression
|
8
5
|
from vellum.workflows.expressions.coalesce_expression import CoalesceExpression
|
9
|
-
from vellum.workflows.expressions.contains import ContainsExpression
|
10
|
-
from vellum.workflows.expressions.does_not_begin_with import DoesNotBeginWithExpression
|
11
|
-
from vellum.workflows.expressions.does_not_contain import DoesNotContainExpression
|
12
|
-
from vellum.workflows.expressions.does_not_end_with import DoesNotEndWithExpression
|
13
|
-
from vellum.workflows.expressions.does_not_equal import DoesNotEqualExpression
|
14
|
-
from vellum.workflows.expressions.ends_with import EndsWithExpression
|
15
|
-
from vellum.workflows.expressions.equals import EqualsExpression
|
16
|
-
from vellum.workflows.expressions.greater_than import GreaterThanExpression
|
17
|
-
from vellum.workflows.expressions.greater_than_or_equal_to import GreaterThanOrEqualToExpression
|
18
|
-
from vellum.workflows.expressions.in_ import InExpression
|
19
|
-
from vellum.workflows.expressions.is_nil import IsNilExpression
|
20
|
-
from vellum.workflows.expressions.is_not_nil import IsNotNilExpression
|
21
|
-
from vellum.workflows.expressions.is_not_null import IsNotNullExpression
|
22
|
-
from vellum.workflows.expressions.is_not_undefined import IsNotUndefinedExpression
|
23
|
-
from vellum.workflows.expressions.is_null import IsNullExpression
|
24
|
-
from vellum.workflows.expressions.is_undefined import IsUndefinedExpression
|
25
|
-
from vellum.workflows.expressions.less_than import LessThanExpression
|
26
|
-
from vellum.workflows.expressions.less_than_or_equal_to import LessThanOrEqualToExpression
|
27
|
-
from vellum.workflows.expressions.not_between import NotBetweenExpression
|
28
|
-
from vellum.workflows.expressions.not_in import NotInExpression
|
29
|
-
from vellum.workflows.expressions.or_ import OrExpression
|
30
6
|
from vellum.workflows.nodes.displayable.bases.utils import primitive_to_vellum_value
|
31
|
-
from vellum.workflows.
|
32
|
-
from vellum.workflows.references import NodeReference, OutputReference
|
7
|
+
from vellum.workflows.references import NodeReference
|
33
8
|
from vellum.workflows.utils.uuids import uuid4_from_hash
|
34
9
|
from vellum_ee.workflows.display.types import WorkflowDisplayContext
|
35
10
|
from vellum_ee.workflows.display.utils.vellum import create_node_input_value_pointer_rule
|
@@ -56,15 +31,6 @@ def create_node_input(
|
|
56
31
|
pointer_type: Optional[Type[NodeInputValuePointerRule]] = ConstantValuePointer,
|
57
32
|
) -> NodeInput:
|
58
33
|
input_id = str(input_id) if input_id else str(uuid4_from_hash(f"{node_id}|{input_name}"))
|
59
|
-
if (
|
60
|
-
isinstance(value, OutputReference)
|
61
|
-
and value.outputs_class._node_class
|
62
|
-
and has_wrapped_node(value.outputs_class._node_class)
|
63
|
-
):
|
64
|
-
wrapped_node = get_wrapped_node(value.outputs_class._node_class)
|
65
|
-
if wrapped_node._is_wrapped_node:
|
66
|
-
value = getattr(wrapped_node.Outputs, value.name)
|
67
|
-
|
68
34
|
rules = create_node_input_value_pointer_rules(value, display_context, pointer_type=pointer_type)
|
69
35
|
return NodeInput(
|
70
36
|
id=input_id,
|
@@ -134,48 +100,3 @@ def create_pointer(
|
|
134
100
|
return ConstantValuePointer(type="CONSTANT_VALUE", data=vellum_variable_value)
|
135
101
|
else:
|
136
102
|
raise ValueError(f"Pointer type {pointer_type} not supported")
|
137
|
-
|
138
|
-
|
139
|
-
def convert_descriptor_to_operator(descriptor: BaseDescriptor) -> str:
|
140
|
-
if isinstance(descriptor, EqualsExpression):
|
141
|
-
return "="
|
142
|
-
elif isinstance(descriptor, DoesNotEqualExpression):
|
143
|
-
return "!="
|
144
|
-
elif isinstance(descriptor, LessThanExpression):
|
145
|
-
return "<"
|
146
|
-
elif isinstance(descriptor, GreaterThanExpression):
|
147
|
-
return ">"
|
148
|
-
elif isinstance(descriptor, LessThanOrEqualToExpression):
|
149
|
-
return "<="
|
150
|
-
elif isinstance(descriptor, GreaterThanOrEqualToExpression):
|
151
|
-
return ">="
|
152
|
-
elif isinstance(descriptor, ContainsExpression):
|
153
|
-
return "contains"
|
154
|
-
elif isinstance(descriptor, BeginsWithExpression):
|
155
|
-
return "beginsWith"
|
156
|
-
elif isinstance(descriptor, EndsWithExpression):
|
157
|
-
return "endsWith"
|
158
|
-
elif isinstance(descriptor, DoesNotContainExpression):
|
159
|
-
return "doesNotContain"
|
160
|
-
elif isinstance(descriptor, DoesNotBeginWithExpression):
|
161
|
-
return "doesNotBeginWith"
|
162
|
-
elif isinstance(descriptor, DoesNotEndWithExpression):
|
163
|
-
return "doesNotEndWith"
|
164
|
-
elif isinstance(descriptor, (IsNullExpression, IsNilExpression, IsUndefinedExpression)):
|
165
|
-
return "null"
|
166
|
-
elif isinstance(descriptor, (IsNotNullExpression, IsNotNilExpression, IsNotUndefinedExpression)):
|
167
|
-
return "notNull"
|
168
|
-
elif isinstance(descriptor, InExpression):
|
169
|
-
return "in"
|
170
|
-
elif isinstance(descriptor, NotInExpression):
|
171
|
-
return "notIn"
|
172
|
-
elif isinstance(descriptor, BetweenExpression):
|
173
|
-
return "between"
|
174
|
-
elif isinstance(descriptor, NotBetweenExpression):
|
175
|
-
return "notBetween"
|
176
|
-
elif isinstance(descriptor, AndExpression):
|
177
|
-
return "and"
|
178
|
-
elif isinstance(descriptor, OrExpression):
|
179
|
-
return "or"
|
180
|
-
else:
|
181
|
-
raise ValueError(f"Unsupported descriptor type: {descriptor}")
|
@@ -88,3 +88,59 @@ def test_vellum_workflow_display__serialize_input_variables_with_capitalized_var
|
|
88
88
|
"extensions": {"color": None},
|
89
89
|
}
|
90
90
|
]
|
91
|
+
|
92
|
+
|
93
|
+
def test_vellum_workflow_display_serialize_valid_handle_ids_for_base_nodes():
|
94
|
+
# GIVEN a workflow between two base nodes
|
95
|
+
class StartNode(BaseNode):
|
96
|
+
pass
|
97
|
+
|
98
|
+
class EndNode(BaseNode):
|
99
|
+
class Outputs(BaseNode.Outputs):
|
100
|
+
hello = "world"
|
101
|
+
|
102
|
+
class Workflow(BaseWorkflow):
|
103
|
+
graph = StartNode >> EndNode
|
104
|
+
|
105
|
+
class Outputs(BaseWorkflow.Outputs):
|
106
|
+
final_value = EndNode.Outputs.hello
|
107
|
+
|
108
|
+
# AND a display class for this workflow
|
109
|
+
workflow_display = get_workflow_display(
|
110
|
+
base_display_class=VellumWorkflowDisplay,
|
111
|
+
workflow_class=Workflow,
|
112
|
+
)
|
113
|
+
|
114
|
+
# WHEN we serialize the workflow
|
115
|
+
exec_config = workflow_display.serialize()
|
116
|
+
|
117
|
+
# THEN the serialized workflow handle ids are valid
|
118
|
+
raw_data = exec_config.get("workflow_raw_data")
|
119
|
+
assert isinstance(raw_data, dict)
|
120
|
+
nodes = raw_data.get("nodes")
|
121
|
+
edges = raw_data.get("edges")
|
122
|
+
|
123
|
+
assert isinstance(nodes, list)
|
124
|
+
assert isinstance(edges, list)
|
125
|
+
|
126
|
+
edge_source_handle_ids = {edge.get("source_handle_id") for edge in edges if isinstance(edge, dict)}
|
127
|
+
edge_target_handle_ids = {edge.get("target_handle_id") for edge in edges if isinstance(edge, dict)}
|
128
|
+
|
129
|
+
for node in nodes:
|
130
|
+
assert isinstance(node, dict)
|
131
|
+
|
132
|
+
if node["type"] in {"ENTRYPOINT", "TERMINAL"}:
|
133
|
+
continue
|
134
|
+
|
135
|
+
ports = node.get("ports")
|
136
|
+
assert isinstance(ports, list)
|
137
|
+
for port in ports:
|
138
|
+
assert isinstance(port, dict)
|
139
|
+
assert (
|
140
|
+
port["id"] in edge_source_handle_ids
|
141
|
+
), f"Port {port['id']} from node {node['label']} not found in edge source handle ids"
|
142
|
+
|
143
|
+
assert isinstance(node["trigger"], dict)
|
144
|
+
assert (
|
145
|
+
node["trigger"]["id"] in edge_target_handle_ids
|
146
|
+
), f"Trigger {node['trigger']['id']} from node {node['label']} not found in edge target handle ids"
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import pytest
|
2
2
|
from uuid import uuid4
|
3
|
-
from typing import Dict, Tuple, Type
|
3
|
+
from typing import Any, Dict, Tuple, Type
|
4
4
|
|
5
5
|
from vellum.workflows.nodes.bases.base import BaseNode
|
6
6
|
from vellum.workflows.references.output import OutputReference
|
@@ -20,11 +20,12 @@ from vellum_ee.workflows.display.workflows.vellum_workflow_display import Vellum
|
|
20
20
|
def serialize_node():
|
21
21
|
def _serialize_node(
|
22
22
|
node_class: Type[NodeType],
|
23
|
+
base_class: type[BaseNodeDisplay[Any]] = BaseNodeDisplay,
|
23
24
|
global_workflow_input_displays: Dict[WorkflowInputReference, WorkflowInputsDisplayType] = {},
|
24
25
|
global_node_displays: Dict[Type[BaseNode], NodeDisplayType] = {},
|
25
26
|
global_node_output_displays: Dict[OutputReference, Tuple[Type[BaseNode], NodeOutputDisplay]] = {},
|
26
27
|
) -> JsonObject:
|
27
|
-
node_display_class = get_node_display_class(
|
28
|
+
node_display_class = get_node_display_class(base_class, node_class)
|
28
29
|
node_display = node_display_class()
|
29
30
|
|
30
31
|
context: WorkflowDisplayContext = WorkflowDisplayContext(
|
@@ -1,47 +1,148 @@
|
|
1
|
-
import
|
1
|
+
from uuid import uuid4
|
2
2
|
|
3
3
|
from deepdiff import DeepDiff
|
4
4
|
|
5
5
|
from vellum.workflows.inputs.base import BaseInputs
|
6
6
|
from vellum.workflows.nodes.bases.base import BaseNode
|
7
|
-
from vellum.workflows.nodes.core.
|
7
|
+
from vellum.workflows.nodes.core.retry_node.node import RetryNode
|
8
|
+
from vellum.workflows.nodes.core.try_node.node import TryNode
|
8
9
|
from vellum.workflows.outputs.base import BaseOutputs
|
9
|
-
from
|
10
|
+
from vellum_ee.workflows.display.base import WorkflowInputsDisplay
|
11
|
+
from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
|
12
|
+
from vellum_ee.workflows.display.nodes.vellum.base_node import BaseNodeDisplay
|
13
|
+
from vellum_ee.workflows.display.nodes.vellum.try_node import BaseTryNodeDisplay
|
10
14
|
|
11
15
|
|
12
16
|
class Inputs(BaseInputs):
|
13
|
-
|
17
|
+
input: str
|
14
18
|
|
15
19
|
|
16
|
-
|
17
|
-
|
20
|
+
@RetryNode.wrap(max_attempts=3)
|
21
|
+
class InnerRetryGenericNode(BaseNode):
|
22
|
+
input = Inputs.input
|
23
|
+
|
24
|
+
class Outputs(BaseOutputs):
|
25
|
+
output: str
|
26
|
+
|
27
|
+
|
28
|
+
class InnerRetryGenericNodeDisplay(BaseNodeDisplay[InnerRetryGenericNode.__wrapped_node__]): # type: ignore
|
29
|
+
pass
|
30
|
+
|
31
|
+
|
32
|
+
class OuterRetryNodeDisplay(BaseNodeDisplay[InnerRetryGenericNode]):
|
33
|
+
pass
|
34
|
+
|
35
|
+
|
36
|
+
def test_serialize_node__retry(serialize_node):
|
37
|
+
input_id = uuid4()
|
38
|
+
serialized_node = serialize_node(
|
39
|
+
node_class=InnerRetryGenericNode,
|
40
|
+
global_workflow_input_displays={Inputs.input: WorkflowInputsDisplay(id=input_id)},
|
41
|
+
global_node_displays={
|
42
|
+
InnerRetryGenericNode.__wrapped_node__: InnerRetryGenericNodeDisplay,
|
43
|
+
InnerRetryGenericNode: OuterRetryNodeDisplay,
|
44
|
+
},
|
45
|
+
)
|
46
|
+
|
47
|
+
serialized_node["adornments"][0]["attributes"] = sorted(
|
48
|
+
serialized_node["adornments"][0]["attributes"], key=lambda x: x["name"]
|
49
|
+
)
|
50
|
+
assert not DeepDiff(
|
51
|
+
{
|
52
|
+
"id": "f2a95e79-7d4b-47ad-b986-4f648297ec65",
|
53
|
+
"label": "InnerRetryGenericNode",
|
54
|
+
"type": "GENERIC",
|
55
|
+
"display_data": {"position": {"x": 0.0, "y": 0.0}},
|
56
|
+
"base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
|
57
|
+
"definition": {
|
58
|
+
"name": "InnerRetryGenericNode",
|
59
|
+
"module": [
|
60
|
+
"vellum_ee",
|
61
|
+
"workflows",
|
62
|
+
"display",
|
63
|
+
"tests",
|
64
|
+
"workflow_serialization",
|
65
|
+
"generic_nodes",
|
66
|
+
"test_adornments_serialization",
|
67
|
+
],
|
68
|
+
},
|
69
|
+
"trigger": {"id": "af9ba01c-4cde-4632-9aa1-7673b42e7bd8", "merge_behavior": "AWAIT_ATTRIBUTES"},
|
70
|
+
"ports": [{"id": "c2ecc6c0-f353-4495-9b93-a61a47248556", "name": "default", "type": "DEFAULT"}],
|
71
|
+
"adornments": [
|
72
|
+
{
|
73
|
+
"id": "5be7d260-74f7-4734-b31b-a46a94539586",
|
74
|
+
"label": "RetryNode",
|
75
|
+
"base": {
|
76
|
+
"name": "RetryNode",
|
77
|
+
"module": ["vellum", "workflows", "nodes", "core", "retry_node", "node"],
|
78
|
+
},
|
79
|
+
"attributes": [
|
80
|
+
{
|
81
|
+
"id": "f388e93b-8c68-4f54-8577-bbd0c9091557",
|
82
|
+
"name": "max_attempts",
|
83
|
+
"value": {"type": "CONSTANT_VALUE", "value": {"type": "NUMBER", "value": 3.0}},
|
84
|
+
},
|
85
|
+
{
|
86
|
+
"id": "73a02e62-4535-4e1f-97b5-1264ca8b1d71",
|
87
|
+
"name": "retry_on_condition",
|
88
|
+
"value": {"type": "CONSTANT_VALUE", "value": {"type": "JSON", "value": None}},
|
89
|
+
},
|
90
|
+
{
|
91
|
+
"id": "c91782e3-140f-4938-9c23-d2a7b85dcdd8",
|
92
|
+
"name": "retry_on_error_code",
|
93
|
+
"value": {"type": "CONSTANT_VALUE", "value": {"type": "JSON", "value": None}},
|
94
|
+
},
|
95
|
+
],
|
96
|
+
}
|
97
|
+
],
|
98
|
+
"attributes": [
|
99
|
+
{
|
100
|
+
"id": "c363daa7-9482-4c0e-aee8-faa080602ee3",
|
101
|
+
"name": "input",
|
102
|
+
"value": {"type": "WORKFLOW_INPUT", "input_variable_id": str(input_id)},
|
103
|
+
}
|
104
|
+
],
|
105
|
+
"outputs": [
|
106
|
+
{"id": "8aaf6cd8-3fa5-4f17-a60f-ec7da5ec6498", "name": "output", "type": "STRING", "value": None}
|
107
|
+
],
|
108
|
+
},
|
109
|
+
serialized_node,
|
110
|
+
)
|
18
111
|
|
19
112
|
|
20
|
-
@
|
21
|
-
class
|
22
|
-
|
23
|
-
foo = Inputs.foo
|
24
|
-
bar = State.bar
|
113
|
+
@TryNode.wrap()
|
114
|
+
class InnerTryGenericNode(BaseNode):
|
115
|
+
input = Inputs.input
|
25
116
|
|
26
117
|
class Outputs(BaseOutputs):
|
27
|
-
|
118
|
+
output: str
|
28
119
|
|
29
|
-
|
30
|
-
|
120
|
+
|
121
|
+
@BaseTryNodeDisplay.wrap()
|
122
|
+
class InnerTryGenericNodeDisplay(BaseNodeDisplay[InnerTryGenericNode]):
|
123
|
+
pass
|
31
124
|
|
32
125
|
|
33
|
-
@pytest.mark.skip(reason="not implemented")
|
34
126
|
def test_serialize_node__try(serialize_node):
|
35
|
-
|
127
|
+
input_id = uuid4()
|
128
|
+
serialized_node = serialize_node(
|
129
|
+
base_class=BaseNodeVellumDisplay,
|
130
|
+
node_class=InnerTryGenericNode,
|
131
|
+
global_workflow_input_displays={Inputs.input: WorkflowInputsDisplay(id=input_id)},
|
132
|
+
global_node_displays={
|
133
|
+
InnerTryGenericNode.__wrapped_node__: InnerTryGenericNodeDisplay,
|
134
|
+
},
|
135
|
+
)
|
136
|
+
|
36
137
|
assert not DeepDiff(
|
37
138
|
{
|
38
|
-
"id":
|
39
|
-
"label": "
|
139
|
+
"id": str(InnerTryGenericNode.__wrapped_node__.__id__),
|
140
|
+
"label": "InnerTryGenericNode",
|
40
141
|
"type": "GENERIC",
|
41
142
|
"display_data": {"position": {"x": 0.0, "y": 0.0}},
|
42
143
|
"base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
|
43
144
|
"definition": {
|
44
|
-
"name": "
|
145
|
+
"name": "InnerTryGenericNode",
|
45
146
|
"module": [
|
46
147
|
"vellum_ee",
|
47
148
|
"workflows",
|
@@ -52,16 +153,32 @@ def test_serialize_node__try(serialize_node):
|
|
52
153
|
"test_adornments_serialization",
|
53
154
|
],
|
54
155
|
},
|
55
|
-
"trigger": {"id": "
|
56
|
-
"ports": [
|
156
|
+
"trigger": {"id": "741f7f75-e921-47a9-8c05-9e66640d0866", "merge_behavior": "AWAIT_ATTRIBUTES"},
|
157
|
+
"ports": [{"id": "1b8f8ab5-a656-4015-926c-80655bbd9cb8", "name": "default", "type": "DEFAULT"}],
|
158
|
+
"adornments": [
|
57
159
|
{
|
58
|
-
"id": "
|
59
|
-
"
|
160
|
+
"id": "3344083c-a32c-4a32-920b-0fb5093448fa",
|
161
|
+
"label": "TryNode",
|
162
|
+
"base": {"name": "TryNode", "module": ["vellum", "workflows", "nodes", "core", "try_node", "node"]},
|
163
|
+
"attributes": [
|
164
|
+
{
|
165
|
+
"id": "ab2fbab0-e2a0-419b-b1ef-ce11ecf11e90",
|
166
|
+
"name": "on_error_code",
|
167
|
+
"value": {"type": "CONSTANT_VALUE", "value": {"type": "JSON", "value": None}},
|
168
|
+
}
|
169
|
+
],
|
60
170
|
}
|
61
171
|
],
|
62
|
-
"
|
63
|
-
|
172
|
+
"attributes": [
|
173
|
+
{
|
174
|
+
"id": "4d8b4c2c-4f92-4c7a-abf0-b9c88a15a790",
|
175
|
+
"name": "input",
|
176
|
+
"value": {"type": "WORKFLOW_INPUT", "input_variable_id": str(input_id)},
|
177
|
+
}
|
178
|
+
],
|
179
|
+
"outputs": [
|
180
|
+
{"id": "63ba929b-bf79-44ee-bd1f-d259dbe8d48e", "name": "output", "type": "STRING", "value": None}
|
181
|
+
],
|
64
182
|
},
|
65
183
|
serialized_node,
|
66
|
-
ignore_order=True,
|
67
184
|
)
|
@@ -44,8 +44,8 @@ def test_serialize_node__constant_value(serialize_node):
|
|
44
44
|
"test_attributes_serialization",
|
45
45
|
],
|
46
46
|
},
|
47
|
-
"trigger": {"id": "279e8228-9b82-43a3-8c31-affc036e3a0b", "merge_behavior": "
|
48
|
-
"ports": [{"id": "
|
47
|
+
"trigger": {"id": "279e8228-9b82-43a3-8c31-affc036e3a0b", "merge_behavior": "AWAIT_ATTRIBUTES"},
|
48
|
+
"ports": [{"id": "7cd373aa-34d1-402d-bcb4-1c8f329b63e9", "type": "DEFAULT", "name": "default"}],
|
49
49
|
"adornments": None,
|
50
50
|
"attributes": [
|
51
51
|
{
|
@@ -96,8 +96,8 @@ def test_serialize_node__workflow_input(serialize_node):
|
|
96
96
|
"test_attributes_serialization",
|
97
97
|
],
|
98
98
|
},
|
99
|
-
"trigger": {"id": "b1a5d749-bac0-4f11-8427-191febb2198e", "merge_behavior": "
|
100
|
-
"ports": [{"id": "
|
99
|
+
"trigger": {"id": "b1a5d749-bac0-4f11-8427-191febb2198e", "merge_behavior": "AWAIT_ATTRIBUTES"},
|
100
|
+
"ports": [{"id": "d15c7175-139c-4885-8ef8-3e4081db121b", "type": "DEFAULT", "name": "default"}],
|
101
101
|
"adornments": None,
|
102
102
|
"attributes": [
|
103
103
|
{
|
@@ -160,8 +160,8 @@ def test_serialize_node__node_output(serialize_node):
|
|
160
160
|
"test_attributes_serialization",
|
161
161
|
],
|
162
162
|
},
|
163
|
-
"trigger": {"id": "449072ba-f7b6-4314-ac96-682123f225e5", "merge_behavior": "
|
164
|
-
"ports": [{"id": "
|
163
|
+
"trigger": {"id": "449072ba-f7b6-4314-ac96-682123f225e5", "merge_behavior": "AWAIT_ATTRIBUTES"},
|
164
|
+
"ports": [{"id": "1879f33e-6efa-46a0-9281-e02bbbc1d413", "type": "DEFAULT", "name": "default"}],
|
165
165
|
"adornments": None,
|
166
166
|
"attributes": [
|
167
167
|
{
|
@@ -210,8 +210,8 @@ def test_serialize_node__vellum_secret(serialize_node):
|
|
210
210
|
"test_attributes_serialization",
|
211
211
|
],
|
212
212
|
},
|
213
|
-
"trigger": {"id": "3ea0305d-d8ea-45fe-8cf1-f6c1c85e6979", "merge_behavior": "
|
214
|
-
"ports": [{"id": "
|
213
|
+
"trigger": {"id": "3ea0305d-d8ea-45fe-8cf1-f6c1c85e6979", "merge_behavior": "AWAIT_ATTRIBUTES"},
|
214
|
+
"ports": [{"id": "881abc1c-ada3-4405-8faf-e167fa2f851b", "type": "DEFAULT", "name": "default"}],
|
215
215
|
"adornments": None,
|
216
216
|
"attributes": [
|
217
217
|
{
|
@@ -266,8 +266,8 @@ def test_serialize_node__node_execution(serialize_node):
|
|
266
266
|
"test_attributes_serialization",
|
267
267
|
],
|
268
268
|
},
|
269
|
-
"trigger": {"id": "68a91426-4c30-4194-a4c0-cff224d3c0f3", "merge_behavior": "
|
270
|
-
"ports": [{"id": "
|
269
|
+
"trigger": {"id": "68a91426-4c30-4194-a4c0-cff224d3c0f3", "merge_behavior": "AWAIT_ATTRIBUTES"},
|
270
|
+
"ports": [{"id": "0e1f78d5-8be1-4533-b2b4-a52777a8d43d", "type": "DEFAULT", "name": "default"}],
|
271
271
|
"adornments": None,
|
272
272
|
"attributes": [
|
273
273
|
{
|
vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py
CHANGED
@@ -40,8 +40,8 @@ def test_serialize_node__annotated_output(serialize_node):
|
|
40
40
|
"test_outputs_serialization",
|
41
41
|
],
|
42
42
|
},
|
43
|
-
"trigger": {"id": "256ef76c-39a6-4a8f-8bda-922f5972a1d4", "merge_behavior": "
|
44
|
-
"ports": [{"id": "
|
43
|
+
"trigger": {"id": "256ef76c-39a6-4a8f-8bda-922f5972a1d4", "merge_behavior": "AWAIT_ATTRIBUTES"},
|
44
|
+
"ports": [{"id": "9f391128-5d83-4c46-a62e-2b8bd075f569", "type": "DEFAULT", "name": "default"}],
|
45
45
|
"adornments": None,
|
46
46
|
"attributes": [],
|
47
47
|
"outputs": [
|
@@ -89,8 +89,8 @@ def test_serialize_node__workflow_input(serialize_node):
|
|
89
89
|
"test_outputs_serialization",
|
90
90
|
],
|
91
91
|
},
|
92
|
-
"trigger": {"id": "b1a5d749-bac0-4f11-8427-191febb2198e", "merge_behavior": "
|
93
|
-
"ports": [{"id": "
|
92
|
+
"trigger": {"id": "b1a5d749-bac0-4f11-8427-191febb2198e", "merge_behavior": "AWAIT_ATTRIBUTES"},
|
93
|
+
"ports": [{"id": "d15c7175-139c-4885-8ef8-3e4081db121b", "type": "DEFAULT", "name": "default"}],
|
94
94
|
"adornments": None,
|
95
95
|
"attributes": [],
|
96
96
|
"outputs": [
|
@@ -155,8 +155,8 @@ def test_serialize_node__node_output_reference(serialize_node):
|
|
155
155
|
"test_outputs_serialization",
|
156
156
|
],
|
157
157
|
},
|
158
|
-
"trigger": {"id": "449072ba-f7b6-4314-ac96-682123f225e5", "merge_behavior": "
|
159
|
-
"ports": [{"id": "
|
158
|
+
"trigger": {"id": "449072ba-f7b6-4314-ac96-682123f225e5", "merge_behavior": "AWAIT_ATTRIBUTES"},
|
159
|
+
"ports": [{"id": "1879f33e-6efa-46a0-9281-e02bbbc1d413", "type": "DEFAULT", "name": "default"}],
|
160
160
|
"adornments": None,
|
161
161
|
"attributes": [],
|
162
162
|
"outputs": [
|