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.
Files changed (33) hide show
  1. vellum/client/core/client_wrapper.py +1 -1
  2. vellum/client/core/pydantic_utilities.py +4 -5
  3. vellum/client/resources/document_indexes/client.py +0 -55
  4. vellum/client/types/document_index_read.py +0 -10
  5. vellum/client/types/logical_operator.py +1 -0
  6. vellum/plugins/pydantic.py +14 -4
  7. vellum/workflows/nodes/core/retry_node/tests/test_node.py +23 -0
  8. vellum/workflows/nodes/displayable/api_node/tests/test_api_node.py +29 -0
  9. vellum/workflows/nodes/displayable/bases/api_node/node.py +2 -2
  10. vellum/workflows/vellum_client.py +9 -5
  11. {vellum_ai-0.14.14.dist-info → vellum_ai-0.14.16.dist-info}/METADATA +2 -2
  12. {vellum_ai-0.14.14.dist-info → vellum_ai-0.14.16.dist-info}/RECORD +33 -32
  13. vellum_cli/image_push.py +76 -42
  14. vellum_cli/tests/test_image_push.py +56 -0
  15. vellum_ee/workflows/display/nodes/base_node_display.py +8 -5
  16. vellum_ee/workflows/display/nodes/base_node_vellum_display.py +1 -4
  17. vellum_ee/workflows/display/nodes/get_node_display_class.py +34 -8
  18. vellum_ee/workflows/display/nodes/vellum/base_adornment_node.py +55 -1
  19. vellum_ee/workflows/display/nodes/vellum/retry_node.py +1 -54
  20. vellum_ee/workflows/display/nodes/vellum/templating_node.py +1 -8
  21. vellum_ee/workflows/display/nodes/vellum/try_node.py +1 -42
  22. vellum_ee/workflows/display/tests/test_vellum_workflow_display.py +47 -10
  23. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +29 -33
  24. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +91 -106
  25. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py +33 -38
  26. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py +197 -145
  27. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py +23 -26
  28. vellum_ee/workflows/display/utils/vellum.py +3 -0
  29. vellum_ee/workflows/display/workflows/base_workflow_display.py +3 -6
  30. vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +52 -0
  31. {vellum_ai-0.14.14.dist-info → vellum_ai-0.14.16.dist-info}/LICENSE +0 -0
  32. {vellum_ai-0.14.14.dist-info → vellum_ai-0.14.16.dist-info}/WHEEL +0 -0
  33. {vellum_ai-0.14.14.dist-info → vellum_ai-0.14.16.dist-info}/entry_points.txt +0 -0
@@ -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": "c2ed23f7-f6cb-4a56-a91c-2e5f9d8fda7f",
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": "9d3a1b3d-4a38-4f2e-bbf1-dd8be152bce8", "merge_behavior": "AWAIT_ATTRIBUTES"},
36
+ "trigger": {"id": "be19c63b-3492-46b1-be9d-16f8d2e6410b", "merge_behavior": "AWAIT_ATTRIBUTES"},
38
37
  "ports": [
39
38
  {
40
- "id": "89dccfa5-cc1a-4612-bd87-86cb444f6dd4",
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": "0ba67f76-aaff-4bd4-a20f-73a32ef5810d",
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": "ffa72187-9a18-453f-ae55-b77aad332630", "merge_behavior": "AWAIT_ANY"},
78
+ "trigger": {"id": "5bb6bb4c-4374-44c8-a7b5-7bb6c1060a5b", "merge_behavior": "AWAIT_ANY"},
81
79
  "ports": [
82
80
  {
83
- "id": "38b83138-cb07-40cb-82d2-83982ded6883",
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": "09d06cd3-06ea-40cc-afd8-17ad88542271",
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": "62074276-c817-476d-b59d-da523ae3f218", "merge_behavior": "AWAIT_ALL"},
120
+ "trigger": {"id": "124ba9cf-a30e-41ef-81bf-143708f8b1c3", "merge_behavior": "AWAIT_ALL"},
124
121
  "ports": [
125
122
  {
126
- "id": "9edef179-a1c2-4624-b185-593bb84f08a0",
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
- str(node.__id__): display_context.node_displays[node] for node in display_context.node_displays
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"}