vellum-ai 0.14.14__py3-none-any.whl → 0.14.16__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/client/core/pydantic_utilities.py +4 -5
- vellum/client/resources/document_indexes/client.py +0 -55
- vellum/client/types/document_index_read.py +0 -10
- vellum/client/types/logical_operator.py +1 -0
- vellum/plugins/pydantic.py +14 -4
- vellum/workflows/nodes/core/retry_node/tests/test_node.py +23 -0
- vellum/workflows/nodes/displayable/api_node/tests/test_api_node.py +29 -0
- vellum/workflows/nodes/displayable/bases/api_node/node.py +2 -2
- vellum/workflows/vellum_client.py +9 -5
- {vellum_ai-0.14.14.dist-info → vellum_ai-0.14.16.dist-info}/METADATA +2 -2
- {vellum_ai-0.14.14.dist-info → vellum_ai-0.14.16.dist-info}/RECORD +33 -32
- vellum_cli/image_push.py +76 -42
- vellum_cli/tests/test_image_push.py +56 -0
- vellum_ee/workflows/display/nodes/base_node_display.py +8 -5
- vellum_ee/workflows/display/nodes/base_node_vellum_display.py +1 -4
- vellum_ee/workflows/display/nodes/get_node_display_class.py +34 -8
- vellum_ee/workflows/display/nodes/vellum/base_adornment_node.py +55 -1
- vellum_ee/workflows/display/nodes/vellum/retry_node.py +1 -54
- vellum_ee/workflows/display/nodes/vellum/templating_node.py +1 -8
- vellum_ee/workflows/display/nodes/vellum/try_node.py +1 -42
- vellum_ee/workflows/display/tests/test_vellum_workflow_display.py +47 -10
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +29 -33
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +91 -106
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py +33 -38
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py +197 -145
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py +23 -26
- vellum_ee/workflows/display/utils/vellum.py +3 -0
- vellum_ee/workflows/display/workflows/base_workflow_display.py +3 -6
- vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +52 -0
- {vellum_ai-0.14.14.dist-info → vellum_ai-0.14.16.dist-info}/LICENSE +0 -0
- {vellum_ai-0.14.14.dist-info → vellum_ai-0.14.16.dist-info}/WHEEL +0 -0
- {vellum_ai-0.14.14.dist-info → vellum_ai-0.14.16.dist-info}/entry_points.txt +0 -0
vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py
CHANGED
@@ -9,16 +9,15 @@ class Inputs(BaseInputs):
|
|
9
9
|
input: str
|
10
10
|
|
11
11
|
|
12
|
-
class BasicGenericNode(BaseNode):
|
13
|
-
pass
|
14
|
-
|
15
|
-
|
16
12
|
def test_serialize_node__basic(serialize_node):
|
13
|
+
class BasicGenericNode(BaseNode):
|
14
|
+
pass
|
15
|
+
|
17
16
|
serialized_node = serialize_node(BasicGenericNode)
|
18
17
|
assert not DeepDiff(
|
19
18
|
{
|
20
|
-
"id": "
|
21
|
-
"label": "BasicGenericNode",
|
19
|
+
"id": "8d7cbfe4-72ca-4367-a401-8d28723d2f00",
|
20
|
+
"label": "test_serialize_node__basic.<locals>.BasicGenericNode",
|
22
21
|
"type": "GENERIC",
|
23
22
|
"display_data": {"position": {"x": 0.0, "y": 0.0}},
|
24
23
|
"base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
|
@@ -34,10 +33,10 @@ def test_serialize_node__basic(serialize_node):
|
|
34
33
|
"test_trigger_serialization",
|
35
34
|
],
|
36
35
|
},
|
37
|
-
"trigger": {"id": "
|
36
|
+
"trigger": {"id": "be19c63b-3492-46b1-be9d-16f8d2e6410b", "merge_behavior": "AWAIT_ATTRIBUTES"},
|
38
37
|
"ports": [
|
39
38
|
{
|
40
|
-
"id": "
|
39
|
+
"id": "8bec8d0c-113f-4110-afcb-4a6e566e7236",
|
41
40
|
"name": "default",
|
42
41
|
"type": "DEFAULT",
|
43
42
|
}
|
@@ -51,17 +50,16 @@ def test_serialize_node__basic(serialize_node):
|
|
51
50
|
)
|
52
51
|
|
53
52
|
|
54
|
-
class AwaitAnyGenericNode(BaseNode):
|
55
|
-
class Trigger(BaseNode.Trigger):
|
56
|
-
merge_behavior = MergeBehavior.AWAIT_ANY
|
57
|
-
|
58
|
-
|
59
53
|
def test_serialize_node__await_any(serialize_node):
|
54
|
+
class AwaitAnyGenericNode(BaseNode):
|
55
|
+
class Trigger(BaseNode.Trigger):
|
56
|
+
merge_behavior = MergeBehavior.AWAIT_ANY
|
57
|
+
|
60
58
|
serialized_node = serialize_node(AwaitAnyGenericNode)
|
61
59
|
assert not DeepDiff(
|
62
60
|
{
|
63
|
-
"id": "
|
64
|
-
"label": "AwaitAnyGenericNode",
|
61
|
+
"id": "42e17f0e-8496-415f-9c72-f85250ba6f0b",
|
62
|
+
"label": "test_serialize_node__await_any.<locals>.AwaitAnyGenericNode",
|
65
63
|
"type": "GENERIC",
|
66
64
|
"display_data": {"position": {"x": 0.0, "y": 0.0}},
|
67
65
|
"base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
|
@@ -77,10 +75,10 @@ def test_serialize_node__await_any(serialize_node):
|
|
77
75
|
"test_trigger_serialization",
|
78
76
|
],
|
79
77
|
},
|
80
|
-
"trigger": {"id": "
|
78
|
+
"trigger": {"id": "5bb6bb4c-4374-44c8-a7b5-7bb6c1060a5b", "merge_behavior": "AWAIT_ANY"},
|
81
79
|
"ports": [
|
82
80
|
{
|
83
|
-
"id": "
|
81
|
+
"id": "d9a84db7-8bd6-4a15-9e3c-c2e898c26d16",
|
84
82
|
"name": "default",
|
85
83
|
"type": "DEFAULT",
|
86
84
|
}
|
@@ -94,17 +92,16 @@ def test_serialize_node__await_any(serialize_node):
|
|
94
92
|
)
|
95
93
|
|
96
94
|
|
97
|
-
class AwaitAllGenericNode(BaseNode):
|
98
|
-
class Trigger(BaseNode.Trigger):
|
99
|
-
merge_behavior = MergeBehavior.AWAIT_ALL
|
100
|
-
|
101
|
-
|
102
95
|
def test_serialize_node__await_all(serialize_node):
|
96
|
+
class AwaitAllGenericNode(BaseNode):
|
97
|
+
class Trigger(BaseNode.Trigger):
|
98
|
+
merge_behavior = MergeBehavior.AWAIT_ALL
|
99
|
+
|
103
100
|
serialized_node = serialize_node(AwaitAllGenericNode)
|
104
101
|
assert not DeepDiff(
|
105
102
|
{
|
106
|
-
"id": "
|
107
|
-
"label": "AwaitAllGenericNode",
|
103
|
+
"id": "b3e1145a-5f41-456b-9382-6d0a1e828c2f",
|
104
|
+
"label": "test_serialize_node__await_all.<locals>.AwaitAllGenericNode",
|
108
105
|
"type": "GENERIC",
|
109
106
|
"display_data": {"position": {"x": 0.0, "y": 0.0}},
|
110
107
|
"base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
|
@@ -120,10 +117,10 @@ def test_serialize_node__await_all(serialize_node):
|
|
120
117
|
"test_trigger_serialization",
|
121
118
|
],
|
122
119
|
},
|
123
|
-
"trigger": {"id": "
|
120
|
+
"trigger": {"id": "124ba9cf-a30e-41ef-81bf-143708f8b1c3", "merge_behavior": "AWAIT_ALL"},
|
124
121
|
"ports": [
|
125
122
|
{
|
126
|
-
"id": "
|
123
|
+
"id": "fa73da35-0bf9-4f02-bf5b-0b0d1a6f1494",
|
127
124
|
"name": "default",
|
128
125
|
"type": "DEFAULT",
|
129
126
|
}
|
@@ -28,6 +28,7 @@ from vellum.workflows.expressions.less_than_or_equal_to import LessThanOrEqualTo
|
|
28
28
|
from vellum.workflows.expressions.not_between import NotBetweenExpression
|
29
29
|
from vellum.workflows.expressions.not_in import NotInExpression
|
30
30
|
from vellum.workflows.expressions.or_ import OrExpression
|
31
|
+
from vellum.workflows.expressions.parse_json import ParseJsonExpression
|
31
32
|
from vellum.workflows.nodes.bases.base import BaseNode
|
32
33
|
from vellum.workflows.nodes.displayable.bases.utils import primitive_to_vellum_value
|
33
34
|
from vellum.workflows.references import OutputReference, WorkflowInputReference
|
@@ -163,5 +164,7 @@ def convert_descriptor_to_operator(descriptor: BaseDescriptor) -> LogicalOperato
|
|
163
164
|
return "or"
|
164
165
|
elif isinstance(descriptor, CoalesceExpression):
|
165
166
|
return "coalesce"
|
167
|
+
elif isinstance(descriptor, ParseJsonExpression):
|
168
|
+
return "parseJson"
|
166
169
|
else:
|
167
170
|
raise ValueError(f"Unsupported descriptor type: {descriptor}")
|
@@ -212,8 +212,6 @@ class BaseWorkflowDisplay(
|
|
212
212
|
|
213
213
|
port_displays: Dict[Port, PortDisplay] = {}
|
214
214
|
|
215
|
-
# TODO: We should still serialize nodes that are in the workflow's directory but aren't used in the graph.
|
216
|
-
# https://app.shortcut.com/vellum/story/5394
|
217
215
|
for node in self._workflow.get_nodes():
|
218
216
|
extracted_node_displays = self._extract_node_displays(node)
|
219
217
|
|
@@ -403,11 +401,11 @@ class BaseWorkflowDisplay(
|
|
403
401
|
for input in display_context.workflow_input_displays
|
404
402
|
}
|
405
403
|
node_displays = {
|
406
|
-
|
404
|
+
node.__id__: (node, display_context.node_displays[node]) for node in display_context.node_displays
|
407
405
|
}
|
408
406
|
node_event_displays = {}
|
409
407
|
for node_id in node_displays:
|
410
|
-
current_node_display = node_displays[node_id]
|
408
|
+
node, current_node_display = node_displays[node_id]
|
411
409
|
input_display = {}
|
412
410
|
if isinstance(current_node_display, BaseNodeVellumDisplay):
|
413
411
|
input_display = current_node_display.node_input_ids_by_name
|
@@ -418,7 +416,6 @@ class BaseWorkflowDisplay(
|
|
418
416
|
port_display_meta = {
|
419
417
|
port.name: current_node_display.port_displays[port].id for port in current_node_display.port_displays
|
420
418
|
}
|
421
|
-
node = current_node_display._node
|
422
419
|
subworkflow_display_context: Optional[WorkflowEventDisplayContext] = None
|
423
420
|
if hasattr(node, "subworkflow"):
|
424
421
|
# All nodes that have a subworkflow attribute are currently expected to call them `subworkflow`
|
@@ -432,7 +429,7 @@ class BaseWorkflowDisplay(
|
|
432
429
|
)
|
433
430
|
subworkflow_display_context = subworkflow_display.get_event_display_context()
|
434
431
|
|
435
|
-
node_event_displays[node_id] = NodeEventDisplayContext(
|
432
|
+
node_event_displays[str(node_id)] = NodeEventDisplayContext(
|
436
433
|
input_display=input_display,
|
437
434
|
output_display=output_display,
|
438
435
|
port_display=port_display_meta,
|
@@ -1,9 +1,13 @@
|
|
1
1
|
import pytest
|
2
|
+
from uuid import uuid4
|
2
3
|
|
3
4
|
from vellum.workflows.nodes.bases.base import BaseNode
|
4
5
|
from vellum.workflows.nodes.core.inline_subworkflow_node.node import InlineSubworkflowNode
|
6
|
+
from vellum.workflows.nodes.core.retry_node.node import RetryNode
|
7
|
+
from vellum.workflows.nodes.core.templating_node.node import TemplatingNode
|
5
8
|
from vellum.workflows.workflows.base import BaseWorkflow
|
6
9
|
from vellum_ee.workflows.display.nodes import BaseNodeDisplay
|
10
|
+
from vellum_ee.workflows.display.nodes.vellum.retry_node import BaseRetryNodeDisplay
|
7
11
|
from vellum_ee.workflows.display.vellum import NodeDisplayData, NodeDisplayPosition
|
8
12
|
from vellum_ee.workflows.display.workflows import VellumWorkflowDisplay
|
9
13
|
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
@@ -139,3 +143,51 @@ def test_get_event_display_context__node_display_to_include_subworkflow_display(
|
|
139
143
|
|
140
144
|
assert node_event_display.subworkflow_display is not None
|
141
145
|
assert str(InnerNode.__id__) in node_event_display.subworkflow_display.node_displays
|
146
|
+
|
147
|
+
|
148
|
+
def test_get_event_display_context__node_display_for_adornment_nodes():
|
149
|
+
# GIVEN a simple workflow with a retry node adornment
|
150
|
+
@RetryNode.wrap(max_attempts=4)
|
151
|
+
class MyNode(BaseNode):
|
152
|
+
pass
|
153
|
+
|
154
|
+
class MyWorkflow(BaseWorkflow):
|
155
|
+
graph = MyNode
|
156
|
+
|
157
|
+
# AND a display class for the node
|
158
|
+
inner_node_id = uuid4()
|
159
|
+
|
160
|
+
@BaseRetryNodeDisplay.wrap()
|
161
|
+
class MyNodeDisplay(BaseNodeDisplay[MyNode]):
|
162
|
+
node_id = inner_node_id
|
163
|
+
|
164
|
+
# WHEN we gather the event display context
|
165
|
+
display_context = VellumWorkflowDisplay(MyWorkflow).get_event_display_context()
|
166
|
+
|
167
|
+
# THEN the subworkflow display should be included
|
168
|
+
assert str(MyNode.__id__) in display_context.node_displays
|
169
|
+
node_event_display = display_context.node_displays[str(MyNode.__id__)]
|
170
|
+
assert node_event_display.subworkflow_display is not None
|
171
|
+
assert str(inner_node_id) in node_event_display.subworkflow_display.node_displays
|
172
|
+
|
173
|
+
|
174
|
+
def test_get_event_display_context__templating_node_input_display():
|
175
|
+
# GIVEN a simple workflow with a templating node referencing another node output
|
176
|
+
class DataNode(BaseNode):
|
177
|
+
class Outputs:
|
178
|
+
bar: str
|
179
|
+
|
180
|
+
class MyNode(TemplatingNode):
|
181
|
+
inputs = {"foo": DataNode.Outputs.bar}
|
182
|
+
|
183
|
+
class MyWorkflow(BaseWorkflow):
|
184
|
+
graph = DataNode >> MyNode
|
185
|
+
|
186
|
+
# WHEN we gather the event display context
|
187
|
+
display_context = VellumWorkflowDisplay(MyWorkflow).get_event_display_context()
|
188
|
+
|
189
|
+
# THEN the subworkflow display should be included
|
190
|
+
assert str(MyNode.__id__) in display_context.node_displays
|
191
|
+
node_event_display = display_context.node_displays[str(MyNode.__id__)]
|
192
|
+
|
193
|
+
assert node_event_display.input_display.keys() == {"inputs.foo"}
|
File without changes
|
File without changes
|
File without changes
|