vellum-ai 0.12.17__py3-none-any.whl → 0.13.1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. vellum/__init__.py +10 -22
  2. vellum/client/__init__.py +8 -0
  3. vellum/client/core/client_wrapper.py +1 -1
  4. vellum/client/core/pydantic_utilities.py +5 -0
  5. vellum/client/resources/__init__.py +4 -0
  6. vellum/client/resources/organizations/__init__.py +2 -0
  7. vellum/client/resources/organizations/client.py +116 -0
  8. vellum/client/resources/workflows/client.py +8 -0
  9. vellum/client/resources/workspaces/__init__.py +2 -0
  10. vellum/client/resources/workspaces/client.py +114 -0
  11. vellum/client/types/__init__.py +6 -22
  12. vellum/client/types/logical_operator.py +2 -0
  13. vellum/client/types/new_member_join_behavior_enum.py +8 -0
  14. vellum/client/types/{function_call_variable_value.py → organization_read.py} +6 -4
  15. vellum/client/types/workflow_execution_workflow_result_event.py +0 -2
  16. vellum/client/types/workflow_result_event.py +0 -2
  17. vellum/client/types/workflow_result_event_output_data_array.py +4 -4
  18. vellum/client/types/{string_variable_value.py → workspace_read.py} +12 -5
  19. vellum/{types/json_variable_value.py → resources/organizations/__init__.py} +1 -1
  20. vellum/resources/organizations/client.py +3 -0
  21. vellum/{types/image_variable_value.py → resources/workspaces/__init__.py} +1 -1
  22. vellum/{types/array_variable_value.py → resources/workspaces/client.py} +1 -1
  23. vellum/types/{array_variable_value_item.py → new_member_join_behavior_enum.py} +1 -1
  24. vellum/types/{audio_variable_value.py → organization_read.py} +1 -1
  25. vellum/types/{error_variable_value.py → workspace_read.py} +1 -1
  26. vellum/workflows/descriptors/base.py +1 -1
  27. vellum/workflows/descriptors/tests/test_utils.py +3 -0
  28. vellum/workflows/expressions/accessor.py +8 -2
  29. vellum/workflows/nodes/core/map_node/node.py +49 -24
  30. vellum/workflows/nodes/core/map_node/tests/test_node.py +4 -4
  31. vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py +1 -1
  32. vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py +5 -3
  33. vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +3 -0
  34. vellum/workflows/nodes/displayable/bases/search_node.py +37 -2
  35. vellum/workflows/nodes/displayable/bases/tests/__init__.py +0 -0
  36. vellum/workflows/nodes/displayable/bases/tests/test_utils.py +61 -0
  37. vellum/workflows/nodes/displayable/bases/types.py +42 -0
  38. vellum/workflows/nodes/displayable/bases/utils.py +112 -0
  39. vellum/workflows/nodes/displayable/inline_prompt_node/tests/test_node.py +0 -1
  40. vellum/workflows/nodes/displayable/search_node/tests/__init__.py +0 -0
  41. vellum/workflows/nodes/displayable/search_node/tests/test_node.py +164 -0
  42. vellum/workflows/nodes/displayable/tests/test_inline_text_prompt_node.py +2 -3
  43. vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py +0 -1
  44. vellum/workflows/runner/runner.py +37 -4
  45. vellum/workflows/types/tests/test_utils.py +5 -2
  46. vellum/workflows/types/utils.py +4 -0
  47. vellum/workflows/workflows/base.py +14 -32
  48. {vellum_ai-0.12.17.dist-info → vellum_ai-0.13.1.dist-info}/METADATA +1 -1
  49. {vellum_ai-0.12.17.dist-info → vellum_ai-0.13.1.dist-info}/RECORD +100 -97
  50. vellum_cli/__init__.py +10 -0
  51. vellum_cli/ping.py +28 -0
  52. vellum_cli/tests/test_ping.py +47 -0
  53. vellum_ee/workflows/display/nodes/base_node_display.py +17 -10
  54. vellum_ee/workflows/display/nodes/vellum/api_node.py +1 -0
  55. vellum_ee/workflows/display/nodes/vellum/base_node.py +110 -2
  56. vellum_ee/workflows/display/nodes/vellum/code_execution_node.py +1 -0
  57. vellum_ee/workflows/display/nodes/vellum/conditional_node.py +5 -62
  58. vellum_ee/workflows/display/nodes/vellum/error_node.py +1 -0
  59. vellum_ee/workflows/display/nodes/vellum/final_output_node.py +1 -0
  60. vellum_ee/workflows/display/nodes/vellum/guardrail_node.py +1 -0
  61. vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py +4 -0
  62. vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py +1 -0
  63. vellum_ee/workflows/display/nodes/vellum/map_node.py +2 -1
  64. vellum_ee/workflows/display/nodes/vellum/merge_node.py +1 -0
  65. vellum_ee/workflows/display/nodes/vellum/note_node.py +1 -0
  66. vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py +15 -10
  67. vellum_ee/workflows/display/nodes/vellum/search_node.py +1 -0
  68. vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py +1 -0
  69. vellum_ee/workflows/display/nodes/vellum/templating_node.py +1 -0
  70. vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py +2 -2
  71. vellum_ee/workflows/display/nodes/vellum/utils.py +71 -1
  72. vellum_ee/workflows/display/tests/test_vellum_workflow_display.py +2 -5
  73. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py +18 -2
  74. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +67 -0
  75. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +66 -0
  76. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py +1015 -0
  77. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py +37 -22
  78. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py +12 -56
  79. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +43 -93
  80. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +31 -151
  81. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py +8 -26
  82. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py +4 -15
  83. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py +9 -44
  84. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +19 -101
  85. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +19 -73
  86. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +9 -44
  87. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py +9 -44
  88. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_serialization.py +8 -6
  89. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py +11 -58
  90. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py +8 -11
  91. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py +7 -30
  92. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py +2 -11
  93. vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py +9 -44
  94. vellum_ee/workflows/display/utils/vellum.py +4 -42
  95. vellum_ee/workflows/display/vellum.py +9 -43
  96. vellum_ee/workflows/display/workflows/vellum_workflow_display.py +7 -10
  97. vellum_ee/workflows/server/virtual_file_loader.py +3 -3
  98. vellum/client/types/array_variable_value.py +0 -27
  99. vellum/client/types/array_variable_value_item.py +0 -29
  100. vellum/client/types/audio_variable_value.py +0 -25
  101. vellum/client/types/chat_history_variable_value.py +0 -21
  102. vellum/client/types/error_variable_value.py +0 -21
  103. vellum/client/types/image_variable_value.py +0 -25
  104. vellum/client/types/json_variable_value.py +0 -20
  105. vellum/client/types/number_variable_value.py +0 -20
  106. vellum/client/types/search_results_variable_value.py +0 -21
  107. vellum/types/chat_history_variable_value.py +0 -3
  108. vellum/types/function_call_variable_value.py +0 -3
  109. vellum/types/number_variable_value.py +0 -3
  110. vellum/types/search_results_variable_value.py +0 -3
  111. vellum/types/string_variable_value.py +0 -3
  112. {vellum_ai-0.12.17.dist-info → vellum_ai-0.13.1.dist-info}/LICENSE +0 -0
  113. {vellum_ai-0.12.17.dist-info → vellum_ai-0.13.1.dist-info}/WHEEL +0 -0
  114. {vellum_ai-0.12.17.dist-info → vellum_ai-0.13.1.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,1015 @@
1
+ from uuid import uuid4
2
+
3
+ from deepdiff import DeepDiff
4
+
5
+ from vellum.workflows.inputs.base import BaseInputs
6
+ from vellum.workflows.nodes.bases.base import BaseNode
7
+ from vellum.workflows.ports.port import Port
8
+ from vellum.workflows.references.vellum_secret import VellumSecretReference
9
+ from vellum_ee.workflows.display.base import WorkflowInputsDisplay
10
+ from vellum_ee.workflows.display.nodes.types import NodeOutputDisplay
11
+ from vellum_ee.workflows.display.nodes.vellum.base_node import BaseNodeDisplay
12
+
13
+
14
+ class Inputs(BaseInputs):
15
+ input: str
16
+
17
+
18
+ class BasicGenericNode(BaseNode):
19
+ class Outputs(BaseNode.Outputs):
20
+ output = Inputs.input
21
+
22
+
23
+ def test_serialize_node__basic(serialize_node):
24
+ serialized_node = serialize_node(BasicGenericNode)
25
+ assert not DeepDiff(
26
+ {
27
+ "id": "c2ed23f7-f6cb-4a56-a91c-2e5f9d8fda7f",
28
+ "label": "BasicGenericNode",
29
+ "type": "GENERIC",
30
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
31
+ "base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
32
+ "definition": {
33
+ "name": "BasicGenericNode",
34
+ "module": [
35
+ "vellum_ee",
36
+ "workflows",
37
+ "display",
38
+ "tests",
39
+ "workflow_serialization",
40
+ "generic_nodes",
41
+ "test_ports_serialization",
42
+ ],
43
+ },
44
+ "trigger": {"id": "9d3a1b3d-4a38-4f2e-bbf1-dd8be152bce8", "merge_behavior": "AWAIT_ANY"},
45
+ "ports": [
46
+ {
47
+ "id": "4fbf0fff-a42e-4410-852a-238b5059198e",
48
+ "type": "DEFAULT",
49
+ }
50
+ ],
51
+ "adornments": None,
52
+ "attributes": [],
53
+ },
54
+ serialized_node,
55
+ ignore_order=True,
56
+ )
57
+
58
+
59
+ class IfGenericNode(BaseNode):
60
+ class Outputs(BaseNode.Outputs):
61
+ output = Inputs.input
62
+
63
+ class Ports(BaseNode.Ports):
64
+ if_branch = Port.on_if(Inputs.input.equals("hello"))
65
+
66
+
67
+ def test_serialize_node__if(serialize_node):
68
+ input_id = uuid4()
69
+ serialized_node = serialize_node(
70
+ node_class=IfGenericNode, global_workflow_input_displays={Inputs.input: WorkflowInputsDisplay(id=input_id)}
71
+ )
72
+
73
+ assert not DeepDiff(
74
+ {
75
+ "id": "31da54ae-1abb-4e9e-8a7d-6f4f30a78c72",
76
+ "label": "IfGenericNode",
77
+ "type": "GENERIC",
78
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
79
+ "base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
80
+ "definition": {
81
+ "name": "IfGenericNode",
82
+ "module": [
83
+ "vellum_ee",
84
+ "workflows",
85
+ "display",
86
+ "tests",
87
+ "workflow_serialization",
88
+ "generic_nodes",
89
+ "test_ports_serialization",
90
+ ],
91
+ },
92
+ "trigger": {"id": "a8afaebc-7333-4e3f-b221-24452b4a1d47", "merge_behavior": "AWAIT_ANY"},
93
+ "ports": [
94
+ {
95
+ "id": "7605b4c0-a432-4517-b759-5858045a5146",
96
+ "type": "IF",
97
+ "expression": {
98
+ "type": "BINARY_EXPRESSION",
99
+ "lhs": {
100
+ "type": "WORKFLOW_INPUT",
101
+ "input_variable_id": str(input_id),
102
+ },
103
+ "operator": "=",
104
+ "rhs": {
105
+ "type": "CONSTANT_VALUE",
106
+ "value": {
107
+ "type": "STRING",
108
+ "value": "hello",
109
+ },
110
+ },
111
+ },
112
+ }
113
+ ],
114
+ "adornments": None,
115
+ "attributes": [],
116
+ },
117
+ serialized_node,
118
+ ignore_order=True,
119
+ )
120
+
121
+
122
+ class IfElseGenericNode(BaseNode):
123
+ class Outputs(BaseNode.Outputs):
124
+ output = Inputs.input
125
+
126
+ class Ports(BaseNode.Ports):
127
+ if_branch = Port.on_if(Inputs.input.equals("hello"))
128
+ else_branch = Port.on_else()
129
+
130
+
131
+ def test_serialize_node__if_else(serialize_node):
132
+ input_id = uuid4()
133
+ serialized_node = serialize_node(
134
+ node_class=IfElseGenericNode, global_workflow_input_displays={Inputs.input: WorkflowInputsDisplay(id=input_id)}
135
+ )
136
+
137
+ assert not DeepDiff(
138
+ {
139
+ "id": "1f499f82-8cc0-4060-bf4d-d20ac409d4aa",
140
+ "label": "IfElseGenericNode",
141
+ "type": "GENERIC",
142
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
143
+ "base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
144
+ "definition": {
145
+ "name": "IfElseGenericNode",
146
+ "module": [
147
+ "vellum_ee",
148
+ "workflows",
149
+ "display",
150
+ "tests",
151
+ "workflow_serialization",
152
+ "generic_nodes",
153
+ "test_ports_serialization",
154
+ ],
155
+ },
156
+ "trigger": {"id": "5b4f6553-69ca-4844-bbe4-9e5594bc8cae", "merge_behavior": "AWAIT_ANY"},
157
+ "ports": [
158
+ {
159
+ "id": "3eeb7f03-7d65-45aa-b0e5-c7a453f5cbdf",
160
+ "type": "IF",
161
+ "expression": {
162
+ "type": "BINARY_EXPRESSION",
163
+ "lhs": {
164
+ "type": "WORKFLOW_INPUT",
165
+ "input_variable_id": str(input_id),
166
+ },
167
+ "operator": "=",
168
+ "rhs": {
169
+ "type": "CONSTANT_VALUE",
170
+ "value": {
171
+ "type": "STRING",
172
+ "value": "hello",
173
+ },
174
+ },
175
+ },
176
+ },
177
+ {
178
+ "id": "b8472c77-74d5-4432-bf8b-6cd65d3dde06",
179
+ "type": "ELSE",
180
+ "expression": None,
181
+ },
182
+ ],
183
+ "adornments": None,
184
+ "attributes": [],
185
+ },
186
+ serialized_node,
187
+ ignore_order=True,
188
+ )
189
+
190
+
191
+ class IfElifElseGenericNode(BaseNode):
192
+ class Outputs(BaseNode.Outputs):
193
+ output = Inputs.input
194
+
195
+ class Ports(BaseNode.Ports):
196
+ if_branch = Port.on_if(Inputs.input.equals("hello"))
197
+ elif_branch = Port.on_elif(Inputs.input.equals("world"))
198
+ else_branch = Port.on_else()
199
+
200
+
201
+ def test_serialize_node__if_elif_else(serialize_node):
202
+ input_id = uuid4()
203
+ serialized_node = serialize_node(
204
+ node_class=IfElifElseGenericNode,
205
+ global_workflow_input_displays={Inputs.input: WorkflowInputsDisplay(id=input_id)},
206
+ )
207
+ assert not DeepDiff(
208
+ {
209
+ "id": "21c49bfb-a90c-4565-a4e6-8eb5187e81ca",
210
+ "label": "IfElifElseGenericNode",
211
+ "type": "GENERIC",
212
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
213
+ "base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
214
+ "definition": {
215
+ "name": "IfElifElseGenericNode",
216
+ "module": [
217
+ "vellum_ee",
218
+ "workflows",
219
+ "display",
220
+ "tests",
221
+ "workflow_serialization",
222
+ "generic_nodes",
223
+ "test_ports_serialization",
224
+ ],
225
+ },
226
+ "trigger": {"id": "22d55b5b-3545-4498-8658-9d0464202e78", "merge_behavior": "AWAIT_ANY"},
227
+ "ports": [
228
+ {
229
+ "id": "f6e0a2c0-192d-452f-bde4-32fb938e91bc",
230
+ "type": "IF",
231
+ "expression": {
232
+ "type": "BINARY_EXPRESSION",
233
+ "lhs": {
234
+ "type": "WORKFLOW_INPUT",
235
+ "input_variable_id": str(input_id),
236
+ },
237
+ "operator": "=",
238
+ "rhs": {
239
+ "type": "CONSTANT_VALUE",
240
+ "value": {
241
+ "type": "STRING",
242
+ "value": "hello",
243
+ },
244
+ },
245
+ },
246
+ },
247
+ {
248
+ "id": "7e44de04-e816-4da8-9251-cf389442a5d6",
249
+ "type": "ELIF",
250
+ "expression": {
251
+ "type": "BINARY_EXPRESSION",
252
+ "lhs": {
253
+ "type": "WORKFLOW_INPUT",
254
+ "input_variable_id": str(input_id),
255
+ },
256
+ "operator": "=",
257
+ "rhs": {
258
+ "type": "CONSTANT_VALUE",
259
+ "value": {
260
+ "type": "STRING",
261
+ "value": "world",
262
+ },
263
+ },
264
+ },
265
+ },
266
+ {
267
+ "id": "00db3698-ddf5-413b-8408-fff664c212d7",
268
+ "type": "ELSE",
269
+ "expression": None,
270
+ },
271
+ ],
272
+ "adornments": None,
273
+ "attributes": [],
274
+ },
275
+ serialized_node,
276
+ ignore_order=True,
277
+ )
278
+
279
+
280
+ class NodeWithOutput(BaseNode):
281
+ class Outputs(BaseNode.Outputs):
282
+ output = Inputs.input
283
+
284
+
285
+ class NodeWithOutputDisplay(BaseNodeDisplay[NodeWithOutput]):
286
+ pass
287
+
288
+
289
+ class GenericNodeReferencingOutput(BaseNode):
290
+ class Outputs(BaseNode.Outputs):
291
+ output = NodeWithOutput.Outputs.output
292
+
293
+ class Ports(BaseNode.Ports):
294
+ if_branch = Port.on_if(NodeWithOutput.Outputs.output.equals("hello"))
295
+
296
+
297
+ def test_serialize_node__node_output_reference(serialize_node):
298
+ workflow_input_id = uuid4()
299
+ node_output_id = uuid4()
300
+ serialized_node = serialize_node(
301
+ node_class=GenericNodeReferencingOutput,
302
+ global_workflow_input_displays={Inputs.input: WorkflowInputsDisplay(id=workflow_input_id)},
303
+ global_node_displays={NodeWithOutput: NodeWithOutputDisplay()},
304
+ global_node_output_displays={
305
+ NodeWithOutput.Outputs.output: (NodeWithOutput, NodeOutputDisplay(id=node_output_id, name="output"))
306
+ },
307
+ )
308
+
309
+ assert not DeepDiff(
310
+ {
311
+ "id": "c1e2ce60-ac3a-4b17-915e-abe861734e03",
312
+ "label": "GenericNodeReferencingOutput",
313
+ "type": "GENERIC",
314
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
315
+ "definition": {
316
+ "name": "GenericNodeReferencingOutput",
317
+ "module": [
318
+ "vellum_ee",
319
+ "workflows",
320
+ "display",
321
+ "tests",
322
+ "workflow_serialization",
323
+ "generic_nodes",
324
+ "test_ports_serialization",
325
+ ],
326
+ },
327
+ "base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
328
+ "trigger": {"id": "449072ba-f7b6-4314-ac96-682123f225e5", "merge_behavior": "AWAIT_ANY"},
329
+ "ports": [
330
+ {
331
+ "id": "ec9a79b8-65c3-4de8-bd29-42c914d72d4f",
332
+ "type": "IF",
333
+ "expression": {
334
+ "type": "BINARY_EXPRESSION",
335
+ "lhs": {
336
+ "type": "NODE_OUTPUT",
337
+ "node_id": "cd954d76-0b0a-4d9b-9bdf-347179c38cb6",
338
+ "node_output_id": str(node_output_id),
339
+ },
340
+ "operator": "=",
341
+ "rhs": {
342
+ "type": "CONSTANT_VALUE",
343
+ "value": {
344
+ "type": "STRING",
345
+ "value": "hello",
346
+ },
347
+ },
348
+ },
349
+ }
350
+ ],
351
+ "adornments": None,
352
+ "attributes": [],
353
+ },
354
+ serialized_node,
355
+ ignore_order=True,
356
+ )
357
+
358
+
359
+ class GenericNodeReferencingSecret(BaseNode):
360
+ class Outputs(BaseNode.Outputs):
361
+ output = Inputs.input
362
+
363
+ class Ports(BaseNode.Ports):
364
+ if_branch = Port.on_if(VellumSecretReference(name="hello").equals("hello"))
365
+
366
+
367
+ def test_serialize_node__vellum_secret_reference(serialize_node):
368
+ workflow_input_id = uuid4()
369
+ serialized_node = serialize_node(
370
+ node_class=GenericNodeReferencingSecret,
371
+ global_workflow_input_displays={Inputs.input: WorkflowInputsDisplay(id=workflow_input_id)},
372
+ )
373
+
374
+ assert not DeepDiff(
375
+ {
376
+ "id": "88272edd-fc81-403b-bb87-a116ef8f269e",
377
+ "label": "GenericNodeReferencingSecret",
378
+ "type": "GENERIC",
379
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
380
+ "definition": {
381
+ "name": "GenericNodeReferencingSecret",
382
+ "module": [
383
+ "vellum_ee",
384
+ "workflows",
385
+ "display",
386
+ "tests",
387
+ "workflow_serialization",
388
+ "generic_nodes",
389
+ "test_ports_serialization",
390
+ ],
391
+ },
392
+ "base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
393
+ "trigger": {"id": "2709539b-352d-455a-bb86-dba070b59aa1", "merge_behavior": "AWAIT_ANY"},
394
+ "ports": [
395
+ {
396
+ "id": "a353d3f6-2a1f-457c-b8d1-13db5b45be8f",
397
+ "type": "IF",
398
+ "expression": {
399
+ "type": "BINARY_EXPRESSION",
400
+ "lhs": {"type": "VELLUM_SECRET", "vellum_secret_name": "hello"},
401
+ "operator": "=",
402
+ "rhs": {
403
+ "type": "CONSTANT_VALUE",
404
+ "value": {
405
+ "type": "STRING",
406
+ "value": "hello",
407
+ },
408
+ },
409
+ },
410
+ }
411
+ ],
412
+ "adornments": None,
413
+ "attributes": [],
414
+ },
415
+ serialized_node,
416
+ ignore_order=True,
417
+ )
418
+
419
+
420
+ class NodeWithExecutions(BaseNode):
421
+ pass
422
+
423
+
424
+ class NodeWithExecutionsDisplay(BaseNodeDisplay[NodeWithExecutions]):
425
+ pass
426
+
427
+
428
+ class GenericNodeReferencingExecutions(BaseNode):
429
+ class Outputs(BaseNode.Outputs):
430
+ output = NodeWithExecutions.Execution.count
431
+
432
+ class Ports(BaseNode.Ports):
433
+ if_branch = Port.on_if(NodeWithExecutions.Execution.count.equals(5))
434
+
435
+
436
+ def test_serialize_node__execution_count_reference(serialize_node):
437
+ workflow_input_id = uuid4()
438
+ serialized_node = serialize_node(
439
+ node_class=GenericNodeReferencingExecutions,
440
+ global_workflow_input_displays={Inputs.input: WorkflowInputsDisplay(id=workflow_input_id)},
441
+ global_node_displays={NodeWithExecutions: NodeWithExecutionsDisplay()},
442
+ )
443
+
444
+ assert not DeepDiff(
445
+ {
446
+ "id": "6e4d2fb7-891e-492e-97a1-adf44693f518",
447
+ "label": "GenericNodeReferencingExecutions",
448
+ "type": "GENERIC",
449
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
450
+ "definition": {
451
+ "name": "GenericNodeReferencingExecutions",
452
+ "module": [
453
+ "vellum_ee",
454
+ "workflows",
455
+ "display",
456
+ "tests",
457
+ "workflow_serialization",
458
+ "generic_nodes",
459
+ "test_ports_serialization",
460
+ ],
461
+ },
462
+ "base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
463
+ "trigger": {"id": "68a91426-4c30-4194-a4c0-cff224d3c0f3", "merge_behavior": "AWAIT_ANY"},
464
+ "ports": [
465
+ {
466
+ "id": "1794c2eb-5cab-49fe-9354-dfc29f11b374",
467
+ "type": "IF",
468
+ "expression": {
469
+ "type": "BINARY_EXPRESSION",
470
+ "lhs": {
471
+ "type": "EXECUTION_COUNTER",
472
+ "node_id": "c09bd5a6-dc04-4036-90d4-580acd43c71f",
473
+ },
474
+ "operator": "=",
475
+ "rhs": {
476
+ "type": "CONSTANT_VALUE",
477
+ "value": {
478
+ "type": "NUMBER",
479
+ "value": 5,
480
+ },
481
+ },
482
+ },
483
+ }
484
+ ],
485
+ "adornments": None,
486
+ "attributes": [],
487
+ },
488
+ serialized_node,
489
+ ignore_order=True,
490
+ )
491
+
492
+
493
+ class NullGenericNode(BaseNode):
494
+ class Outputs(BaseNode.Outputs):
495
+ output = Inputs.input
496
+
497
+ class Ports(BaseNode.Ports):
498
+ if_branch = Port.on_if(Inputs.input.is_null())
499
+
500
+
501
+ def test_serialize_node__null(serialize_node):
502
+ input_id = uuid4()
503
+ serialized_node = serialize_node(
504
+ node_class=NullGenericNode, global_workflow_input_displays={Inputs.input: WorkflowInputsDisplay(id=input_id)}
505
+ )
506
+
507
+ assert not DeepDiff(
508
+ {
509
+ "id": "d5fe72cd-a2bd-4f91-ae13-44e4c617815e",
510
+ "label": "NullGenericNode",
511
+ "type": "GENERIC",
512
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
513
+ "base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
514
+ "definition": {
515
+ "name": "NullGenericNode",
516
+ "module": [
517
+ "vellum_ee",
518
+ "workflows",
519
+ "display",
520
+ "tests",
521
+ "workflow_serialization",
522
+ "generic_nodes",
523
+ "test_ports_serialization",
524
+ ],
525
+ },
526
+ "trigger": {"id": "26b257ed-6a7d-4ca3-a5c8-d17ba1e776ba", "merge_behavior": "AWAIT_ANY"},
527
+ "ports": [
528
+ {
529
+ "id": "51932d23-492e-4b3b-8b03-6ad7303a80c9",
530
+ "type": "IF",
531
+ "expression": {
532
+ "type": "UNARY_EXPRESSION",
533
+ "lhs": {
534
+ "type": "WORKFLOW_INPUT",
535
+ "input_variable_id": str(input_id),
536
+ },
537
+ "operator": "null",
538
+ },
539
+ }
540
+ ],
541
+ "adornments": None,
542
+ "attributes": [],
543
+ },
544
+ serialized_node,
545
+ ignore_order=True,
546
+ )
547
+
548
+
549
+ class IntegerInputs(BaseInputs):
550
+ input: int
551
+
552
+
553
+ class BetweenGenericNode(BaseNode):
554
+ class Outputs(BaseNode.Outputs):
555
+ output = IntegerInputs.input
556
+
557
+ class Ports(BaseNode.Ports):
558
+ if_branch = Port.on_if(IntegerInputs.input.between(1, 10))
559
+
560
+
561
+ def test_serialize_node__between(serialize_node):
562
+ input_id = uuid4()
563
+ serialized_node = serialize_node(
564
+ node_class=BetweenGenericNode,
565
+ global_workflow_input_displays={IntegerInputs.input: WorkflowInputsDisplay(id=input_id)},
566
+ )
567
+
568
+ assert not DeepDiff(
569
+ {
570
+ "id": "3ef33a2a-6ad5-415c-be75-f38cc1403dfc",
571
+ "label": "BetweenGenericNode",
572
+ "type": "GENERIC",
573
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
574
+ "base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
575
+ "definition": {
576
+ "name": "BetweenGenericNode",
577
+ "module": [
578
+ "vellum_ee",
579
+ "workflows",
580
+ "display",
581
+ "tests",
582
+ "workflow_serialization",
583
+ "generic_nodes",
584
+ "test_ports_serialization",
585
+ ],
586
+ },
587
+ "trigger": {"id": "086a355e-d9ef-4039-af35-9f1211497b32", "merge_behavior": "AWAIT_ANY"},
588
+ "ports": [
589
+ {
590
+ "id": "a86bd19f-a9f7-45c3-80ff-73330b1b75af",
591
+ "type": "IF",
592
+ "expression": {
593
+ "type": "TERNARY_EXPRESSION",
594
+ "base": {
595
+ "type": "WORKFLOW_INPUT",
596
+ "input_variable_id": str(input_id),
597
+ },
598
+ "operator": "between",
599
+ "lhs": {
600
+ "type": "CONSTANT_VALUE",
601
+ "value": {
602
+ "type": "NUMBER",
603
+ "value": 1,
604
+ },
605
+ },
606
+ "rhs": {
607
+ "type": "CONSTANT_VALUE",
608
+ "value": {
609
+ "type": "NUMBER",
610
+ "value": 10,
611
+ },
612
+ },
613
+ },
614
+ }
615
+ ],
616
+ "adornments": None,
617
+ "attributes": [],
618
+ },
619
+ serialized_node,
620
+ ignore_order=True,
621
+ )
622
+
623
+
624
+ class OrGenericNode(BaseNode):
625
+ class Outputs(BaseNode.Outputs):
626
+ output = Inputs.input
627
+
628
+ class Ports(BaseNode.Ports):
629
+ if_branch = Port.on_if(Inputs.input.equals("hello") | Inputs.input.equals("world"))
630
+
631
+
632
+ def test_serialize_node__or(serialize_node):
633
+ input_id = uuid4()
634
+ serialized_node = serialize_node(
635
+ node_class=OrGenericNode, global_workflow_input_displays={Inputs.input: WorkflowInputsDisplay(id=input_id)}
636
+ )
637
+
638
+ assert not DeepDiff(
639
+ {
640
+ "id": "63900268-b9d0-4285-8ea4-7c478f4abf88",
641
+ "label": "OrGenericNode",
642
+ "type": "GENERIC",
643
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
644
+ "base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
645
+ "definition": {
646
+ "name": "OrGenericNode",
647
+ "module": [
648
+ "vellum_ee",
649
+ "workflows",
650
+ "display",
651
+ "tests",
652
+ "workflow_serialization",
653
+ "generic_nodes",
654
+ "test_ports_serialization",
655
+ ],
656
+ },
657
+ "trigger": {"id": "dc245f37-9be7-4097-a50a-4f7196e24313", "merge_behavior": "AWAIT_ANY"},
658
+ "ports": [
659
+ {
660
+ "id": "652a42f9-f4e7-4791-8167-8903ff839520",
661
+ "type": "IF",
662
+ "expression": {
663
+ "type": "BINARY_EXPRESSION",
664
+ "lhs": {
665
+ "type": "BINARY_EXPRESSION",
666
+ "lhs": {
667
+ "type": "WORKFLOW_INPUT",
668
+ "input_variable_id": str(input_id),
669
+ },
670
+ "operator": "=",
671
+ "rhs": {
672
+ "type": "CONSTANT_VALUE",
673
+ "value": {
674
+ "type": "STRING",
675
+ "value": "hello",
676
+ },
677
+ },
678
+ },
679
+ "operator": "or",
680
+ "rhs": {
681
+ "type": "BINARY_EXPRESSION",
682
+ "lhs": {
683
+ "type": "WORKFLOW_INPUT",
684
+ "input_variable_id": str(input_id),
685
+ },
686
+ "operator": "=",
687
+ "rhs": {
688
+ "type": "CONSTANT_VALUE",
689
+ "value": {
690
+ "type": "STRING",
691
+ "value": "world",
692
+ },
693
+ },
694
+ },
695
+ },
696
+ }
697
+ ],
698
+ "adornments": None,
699
+ "attributes": [],
700
+ },
701
+ serialized_node,
702
+ ignore_order=True,
703
+ )
704
+
705
+
706
+ class AndThenOrGenericNode(BaseNode):
707
+ class Outputs(BaseNode.Outputs):
708
+ output = Inputs.input
709
+
710
+ class Ports(BaseNode.Ports):
711
+ if_branch = Port.on_if(
712
+ Inputs.input.equals("hello") & Inputs.input.equals("then") | Inputs.input.equals("world")
713
+ )
714
+
715
+
716
+ def test_serialize_node__and_then_or(serialize_node):
717
+ input_id = uuid4()
718
+ serialized_node = serialize_node(
719
+ node_class=AndThenOrGenericNode,
720
+ global_workflow_input_displays={Inputs.input: WorkflowInputsDisplay(id=input_id)},
721
+ )
722
+
723
+ assert not DeepDiff(
724
+ {
725
+ "id": "b3908206-e540-4dac-9c64-a2e12b847b15",
726
+ "label": "AndThenOrGenericNode",
727
+ "type": "GENERIC",
728
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
729
+ "base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
730
+ "definition": {
731
+ "name": "AndThenOrGenericNode",
732
+ "module": [
733
+ "vellum_ee",
734
+ "workflows",
735
+ "display",
736
+ "tests",
737
+ "workflow_serialization",
738
+ "generic_nodes",
739
+ "test_ports_serialization",
740
+ ],
741
+ },
742
+ "trigger": {"id": "33cfa8f4-bfc5-40b3-8df8-ab86371c26e0", "merge_behavior": "AWAIT_ANY"},
743
+ "ports": [
744
+ {
745
+ "id": "42c89e95-6bbf-4e85-8f26-d4b6fc55d99c",
746
+ "type": "IF",
747
+ "expression": {
748
+ "type": "BINARY_EXPRESSION",
749
+ "lhs": {
750
+ "type": "BINARY_EXPRESSION",
751
+ "lhs": {
752
+ "type": "BINARY_EXPRESSION",
753
+ "lhs": {
754
+ "type": "WORKFLOW_INPUT",
755
+ "input_variable_id": str(input_id),
756
+ },
757
+ "operator": "=",
758
+ "rhs": {
759
+ "type": "CONSTANT_VALUE",
760
+ "value": {
761
+ "type": "STRING",
762
+ "value": "hello",
763
+ },
764
+ },
765
+ },
766
+ "operator": "and",
767
+ "rhs": {
768
+ "type": "BINARY_EXPRESSION",
769
+ "lhs": {
770
+ "type": "WORKFLOW_INPUT",
771
+ "input_variable_id": str(input_id),
772
+ },
773
+ "operator": "=",
774
+ "rhs": {
775
+ "type": "CONSTANT_VALUE",
776
+ "value": {
777
+ "type": "STRING",
778
+ "value": "then",
779
+ },
780
+ },
781
+ },
782
+ },
783
+ "operator": "or",
784
+ "rhs": {
785
+ "type": "BINARY_EXPRESSION",
786
+ "lhs": {
787
+ "type": "WORKFLOW_INPUT",
788
+ "input_variable_id": str(input_id),
789
+ },
790
+ "operator": "=",
791
+ "rhs": {
792
+ "type": "CONSTANT_VALUE",
793
+ "value": {
794
+ "type": "STRING",
795
+ "value": "world",
796
+ },
797
+ },
798
+ },
799
+ },
800
+ }
801
+ ],
802
+ "adornments": None,
803
+ "attributes": [],
804
+ },
805
+ serialized_node,
806
+ ignore_order=True,
807
+ )
808
+
809
+
810
+ class ParenthesizedAndThenOrGenericNode(BaseNode):
811
+ class Outputs(BaseNode.Outputs):
812
+ output = Inputs.input
813
+
814
+ class Ports(BaseNode.Ports):
815
+ if_branch = Port.on_if(
816
+ Inputs.input.equals("hello") & (Inputs.input.equals("then") | Inputs.input.equals("world"))
817
+ )
818
+
819
+
820
+ def test_serialize_node__parenthesized_and_then_or(serialize_node):
821
+ input_id = uuid4()
822
+ serialized_node = serialize_node(
823
+ node_class=ParenthesizedAndThenOrGenericNode,
824
+ global_workflow_input_displays={Inputs.input: WorkflowInputsDisplay(id=input_id)},
825
+ )
826
+
827
+ assert not DeepDiff(
828
+ {
829
+ "id": "6ed0373a-13b1-4edb-b0c4-31642cf312f8",
830
+ "label": "ParenthesizedAndThenOrGenericNode",
831
+ "type": "GENERIC",
832
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
833
+ "base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
834
+ "definition": {
835
+ "name": "ParenthesizedAndThenOrGenericNode",
836
+ "module": [
837
+ "vellum_ee",
838
+ "workflows",
839
+ "display",
840
+ "tests",
841
+ "workflow_serialization",
842
+ "generic_nodes",
843
+ "test_ports_serialization",
844
+ ],
845
+ },
846
+ "trigger": {"id": "91ac3b05-c931-4a4c-bb48-c2ba0e883867", "merge_behavior": "AWAIT_ANY"},
847
+ "ports": [
848
+ {
849
+ "id": "cc07394b-f20b-4370-8a5b-af90e847a73f",
850
+ "type": "IF",
851
+ "expression": {
852
+ "type": "BINARY_EXPRESSION",
853
+ "lhs": {
854
+ "type": "BINARY_EXPRESSION",
855
+ "lhs": {
856
+ "type": "WORKFLOW_INPUT",
857
+ "input_variable_id": str(input_id),
858
+ },
859
+ "operator": "=",
860
+ "rhs": {
861
+ "type": "CONSTANT_VALUE",
862
+ "value": {
863
+ "type": "STRING",
864
+ "value": "hello",
865
+ },
866
+ },
867
+ },
868
+ "operator": "and",
869
+ "rhs": {
870
+ "type": "BINARY_EXPRESSION",
871
+ "lhs": {
872
+ "type": "BINARY_EXPRESSION",
873
+ "lhs": {
874
+ "type": "WORKFLOW_INPUT",
875
+ "input_variable_id": str(input_id),
876
+ },
877
+ "operator": "=",
878
+ "rhs": {
879
+ "type": "CONSTANT_VALUE",
880
+ "value": {
881
+ "type": "STRING",
882
+ "value": "then",
883
+ },
884
+ },
885
+ },
886
+ "operator": "or",
887
+ "rhs": {
888
+ "type": "BINARY_EXPRESSION",
889
+ "lhs": {
890
+ "type": "WORKFLOW_INPUT",
891
+ "input_variable_id": str(input_id),
892
+ },
893
+ "operator": "=",
894
+ "rhs": {
895
+ "type": "CONSTANT_VALUE",
896
+ "value": {
897
+ "type": "STRING",
898
+ "value": "world",
899
+ },
900
+ },
901
+ },
902
+ },
903
+ },
904
+ }
905
+ ],
906
+ "adornments": None,
907
+ "attributes": [],
908
+ },
909
+ serialized_node,
910
+ ignore_order=True,
911
+ )
912
+
913
+
914
+ class OrThenAndGenericNode(BaseNode):
915
+ class Outputs(BaseNode.Outputs):
916
+ output = Inputs.input
917
+
918
+ class Ports(BaseNode.Ports):
919
+ if_branch = Port.on_if(
920
+ Inputs.input.equals("hello") | Inputs.input.equals("then") & Inputs.input.equals("world")
921
+ )
922
+
923
+
924
+ def test_serialize_node__or_then_and(serialize_node):
925
+ input_id = uuid4()
926
+ serialized_node = serialize_node(
927
+ node_class=OrThenAndGenericNode,
928
+ global_workflow_input_displays={Inputs.input: WorkflowInputsDisplay(id=input_id)},
929
+ )
930
+
931
+ assert not DeepDiff(
932
+ {
933
+ "id": "a0e0a35b-132e-4168-ad7d-ceb04f3203f2",
934
+ "label": "OrThenAndGenericNode",
935
+ "type": "GENERIC",
936
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
937
+ "base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
938
+ "definition": {
939
+ "name": "OrThenAndGenericNode",
940
+ "module": [
941
+ "vellum_ee",
942
+ "workflows",
943
+ "display",
944
+ "tests",
945
+ "workflow_serialization",
946
+ "generic_nodes",
947
+ "test_ports_serialization",
948
+ ],
949
+ },
950
+ "trigger": {"id": "dfa53d32-36cc-4b1d-adad-d4de21ac1e5a", "merge_behavior": "AWAIT_ANY"},
951
+ "ports": [
952
+ {
953
+ "id": "daaff604-da1e-45e6-b3df-5bc8de8d55fe",
954
+ "type": "IF",
955
+ "expression": {
956
+ "type": "BINARY_EXPRESSION",
957
+ "lhs": {
958
+ "type": "BINARY_EXPRESSION",
959
+ "lhs": {
960
+ "type": "WORKFLOW_INPUT",
961
+ "input_variable_id": str(input_id),
962
+ },
963
+ "operator": "=",
964
+ "rhs": {
965
+ "type": "CONSTANT_VALUE",
966
+ "value": {
967
+ "type": "STRING",
968
+ "value": "hello",
969
+ },
970
+ },
971
+ },
972
+ "operator": "or",
973
+ "rhs": {
974
+ "type": "BINARY_EXPRESSION",
975
+ "lhs": {
976
+ "type": "BINARY_EXPRESSION",
977
+ "lhs": {
978
+ "type": "WORKFLOW_INPUT",
979
+ "input_variable_id": str(input_id),
980
+ },
981
+ "operator": "=",
982
+ "rhs": {
983
+ "type": "CONSTANT_VALUE",
984
+ "value": {
985
+ "type": "STRING",
986
+ "value": "then",
987
+ },
988
+ },
989
+ },
990
+ "operator": "and",
991
+ "rhs": {
992
+ "type": "BINARY_EXPRESSION",
993
+ "lhs": {
994
+ "type": "WORKFLOW_INPUT",
995
+ "input_variable_id": str(input_id),
996
+ },
997
+ "operator": "=",
998
+ "rhs": {
999
+ "type": "CONSTANT_VALUE",
1000
+ "value": {
1001
+ "type": "STRING",
1002
+ "value": "world",
1003
+ },
1004
+ },
1005
+ },
1006
+ },
1007
+ },
1008
+ }
1009
+ ],
1010
+ "adornments": None,
1011
+ "attributes": [],
1012
+ },
1013
+ serialized_node,
1014
+ ignore_order=True,
1015
+ )