vellum-ai 0.14.44__py3-none-any.whl → 0.14.46__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 (56) hide show
  1. vellum/client/core/client_wrapper.py +1 -1
  2. vellum/client/core/pydantic_utilities.py +7 -1
  3. vellum/workflows/nodes/bases/base.py +1 -0
  4. vellum/workflows/nodes/bases/tests/test_base_node.py +20 -0
  5. vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +8 -14
  6. vellum/workflows/nodes/displayable/code_execution_node/tests/test_code_execution_node.py +62 -0
  7. vellum/workflows/nodes/displayable/code_execution_node/utils.py +3 -54
  8. vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py +5 -6
  9. vellum/workflows/nodes/utils.py +4 -0
  10. vellum/workflows/ports/port.py +13 -3
  11. vellum/workflows/types/code_execution_node_wrappers.py +64 -0
  12. vellum/workflows/types/tests/test_utils.py +3 -3
  13. vellum/workflows/types/utils.py +31 -10
  14. vellum/workflows/vellum_client.py +19 -7
  15. {vellum_ai-0.14.44.dist-info → vellum_ai-0.14.46.dist-info}/METADATA +1 -1
  16. {vellum_ai-0.14.44.dist-info → vellum_ai-0.14.46.dist-info}/RECORD +56 -53
  17. vellum_cli/config.py +7 -2
  18. vellum_cli/push.py +5 -1
  19. vellum_cli/tests/test_push.py +192 -8
  20. vellum_ee/workflows/display/nodes/base_node_display.py +4 -173
  21. vellum_ee/workflows/display/nodes/vellum/conditional_node.py +1 -1
  22. vellum_ee/workflows/display/nodes/vellum/final_output_node.py +2 -1
  23. vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py +5 -6
  24. vellum_ee/workflows/display/nodes/vellum/retry_node.py +3 -3
  25. vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py +5 -6
  26. vellum_ee/workflows/display/nodes/vellum/tests/test_prompt_deployment_node.py +106 -0
  27. vellum_ee/workflows/display/nodes/vellum/tests/test_subworkflow_deployment_node.py +109 -0
  28. vellum_ee/workflows/display/nodes/vellum/try_node.py +3 -3
  29. vellum_ee/workflows/display/tests/test_base_workflow_display.py +1 -0
  30. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +73 -111
  31. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py +0 -1
  32. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +0 -3
  33. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +0 -4
  34. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_default_state_serialization.py +0 -1
  35. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py +0 -1
  36. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py +0 -1
  37. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py +0 -1
  38. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +18 -2
  39. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +10 -1
  40. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +0 -1
  41. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py +2 -3
  42. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_serialization.py +0 -1
  43. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py +2 -3
  44. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py +0 -1
  45. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py +1 -2
  46. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py +0 -1
  47. vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py +5 -55
  48. vellum_ee/workflows/display/types.py +3 -0
  49. vellum_ee/workflows/display/utils/expressions.py +222 -2
  50. vellum_ee/workflows/display/utils/vellum.py +1 -79
  51. vellum_ee/workflows/display/workflows/base_workflow_display.py +59 -37
  52. vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py +3 -0
  53. vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +98 -0
  54. {vellum_ai-0.14.44.dist-info → vellum_ai-0.14.46.dist-info}/LICENSE +0 -0
  55. {vellum_ai-0.14.44.dist-info → vellum_ai-0.14.46.dist-info}/WHEEL +0 -0
  56. {vellum_ai-0.14.44.dist-info → vellum_ai-0.14.46.dist-info}/entry_points.txt +0 -0
@@ -237,124 +237,86 @@ def test_serialize_node__stacked():
237
237
  exec_config = workflow_display.serialize()
238
238
 
239
239
  # THEN the workflow display is created successfully
240
+ assert isinstance(exec_config["workflow_raw_data"], dict)
241
+ assert isinstance(exec_config["workflow_raw_data"]["nodes"], list)
242
+ inner_stacked_generic_node = [
243
+ node
244
+ for node in exec_config["workflow_raw_data"]["nodes"]
245
+ if isinstance(node, dict) and node["type"] == "GENERIC"
246
+ ][0]
240
247
  assert not DeepDiff(
241
248
  {
242
- "workflow_raw_data": {
243
- "nodes": [
244
- {
245
- "id": "c14c1c9b-a7a4-4d2c-84fb-c940cfb09525",
246
- "type": "ENTRYPOINT",
247
- "inputs": [],
248
- "data": {
249
- "label": "Entrypoint Node",
250
- "source_handle_id": "51a5eb25-af14-4bee-9ced-d2aa534ea8e9",
251
- },
252
- "display_data": {"position": {"x": 0.0, "y": 0.0}},
253
- "base": None,
254
- "definition": None,
249
+ "id": "074833b0-e142-4bbc-8dec-209a35e178a3",
250
+ "label": "test_serialize_node__stacked.<locals>.InnerStackedGenericNode",
251
+ "type": "GENERIC",
252
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
253
+ "base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
254
+ "definition": {
255
+ "name": "InnerStackedGenericNode",
256
+ "module": [
257
+ "vellum_ee",
258
+ "workflows",
259
+ "display",
260
+ "tests",
261
+ "workflow_serialization",
262
+ "generic_nodes",
263
+ "test_adornments_serialization",
264
+ ],
265
+ },
266
+ "trigger": {
267
+ "id": "6e4af17f-bbee-4777-b10d-af042cd6e16a",
268
+ "merge_behavior": "AWAIT_ATTRIBUTES",
269
+ },
270
+ "ports": [{"id": "408cd5fb-3a3e-4eb2-9889-61111bd6a129", "name": "default", "type": "DEFAULT"}],
271
+ "adornments": [
272
+ {
273
+ "id": "5be7d260-74f7-4734-b31b-a46a94539586",
274
+ "label": "RetryNode",
275
+ "base": {
276
+ "name": "RetryNode",
277
+ "module": ["vellum", "workflows", "nodes", "core", "retry_node", "node"],
255
278
  },
256
- {
257
- "id": "074833b0-e142-4bbc-8dec-209a35e178a3",
258
- "label": "test_serialize_node__stacked.<locals>.InnerStackedGenericNode",
259
- "type": "GENERIC",
260
- "display_data": {"position": {"x": 0.0, "y": 0.0}},
261
- "base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
262
- "definition": {
263
- "name": "InnerStackedGenericNode",
264
- "module": [
265
- "vellum_ee",
266
- "workflows",
267
- "display",
268
- "tests",
269
- "workflow_serialization",
270
- "generic_nodes",
271
- "test_adornments_serialization",
272
- ],
279
+ "attributes": [
280
+ {
281
+ "id": "f388e93b-8c68-4f54-8577-bbd0c9091557",
282
+ "name": "max_attempts",
283
+ "value": {"type": "CONSTANT_VALUE", "value": {"type": "NUMBER", "value": 5.0}},
273
284
  },
274
- "trigger": {
275
- "id": "6e4af17f-bbee-4777-b10d-af042cd6e16a",
276
- "merge_behavior": "AWAIT_ATTRIBUTES",
285
+ {
286
+ "id": "8a07dc58-3fed-41d4-8ca6-31ee0bb86c61",
287
+ "name": "delay",
288
+ "value": {"type": "CONSTANT_VALUE", "value": {"type": "JSON", "value": None}},
289
+ },
290
+ {
291
+ "id": "c91782e3-140f-4938-9c23-d2a7b85dcdd8",
292
+ "name": "retry_on_error_code",
293
+ "value": {"type": "CONSTANT_VALUE", "value": {"type": "JSON", "value": None}},
277
294
  },
278
- "ports": [{"id": "408cd5fb-3a3e-4eb2-9889-61111bd6a129", "name": "default", "type": "DEFAULT"}],
279
- "adornments": [
280
- {
281
- "id": "5be7d260-74f7-4734-b31b-a46a94539586",
282
- "label": "RetryNode",
283
- "base": {
284
- "name": "RetryNode",
285
- "module": ["vellum", "workflows", "nodes", "core", "retry_node", "node"],
286
- },
287
- "attributes": [
288
- {
289
- "id": "c91782e3-140f-4938-9c23-d2a7b85dcdd8",
290
- "name": "retry_on_error_code",
291
- "value": {"type": "CONSTANT_VALUE", "value": {"type": "JSON", "value": None}},
292
- },
293
- {
294
- "id": "f388e93b-8c68-4f54-8577-bbd0c9091557",
295
- "name": "max_attempts",
296
- "value": {"type": "CONSTANT_VALUE", "value": {"type": "NUMBER", "value": 5}},
297
- },
298
- {
299
- "id": "8a07dc58-3fed-41d4-8ca6-31ee0bb86c61",
300
- "name": "delay",
301
- "value": {"type": "CONSTANT_VALUE", "value": {"type": "JSON", "value": None}},
302
- },
303
- {
304
- "id": "73a02e62-4535-4e1f-97b5-1264ca8b1d71",
305
- "name": "retry_on_condition",
306
- "value": {"type": "CONSTANT_VALUE", "value": {"type": "JSON", "value": None}},
307
- },
308
- ],
309
- },
310
- {
311
- "id": "3344083c-a32c-4a32-920b-0fb5093448fa",
312
- "label": "TryNode",
313
- "base": {
314
- "name": "TryNode",
315
- "module": ["vellum", "workflows", "nodes", "core", "try_node", "node"],
316
- },
317
- "attributes": [
318
- {
319
- "id": "ab2fbab0-e2a0-419b-b1ef-ce11ecf11e90",
320
- "name": "on_error_code",
321
- "value": {"type": "CONSTANT_VALUE", "value": {"type": "JSON", "value": None}},
322
- }
323
- ],
324
- },
325
- ],
326
- "attributes": [],
327
- "outputs": [],
295
+ {
296
+ "id": "73a02e62-4535-4e1f-97b5-1264ca8b1d71",
297
+ "name": "retry_on_condition",
298
+ "value": {"type": "CONSTANT_VALUE", "value": {"type": "JSON", "value": None}},
299
+ },
300
+ ],
301
+ },
302
+ {
303
+ "id": "3344083c-a32c-4a32-920b-0fb5093448fa",
304
+ "label": "TryNode",
305
+ "base": {
306
+ "name": "TryNode",
307
+ "module": ["vellum", "workflows", "nodes", "core", "try_node", "node"],
328
308
  },
329
- ],
330
- "edges": [
331
- {
332
- "id": "e8bd50dd-37a0-49b0-8b7b-f1dd8eb478b9",
333
- "source_node_id": "c14c1c9b-a7a4-4d2c-84fb-c940cfb09525",
334
- "source_handle_id": "51a5eb25-af14-4bee-9ced-d2aa534ea8e9",
335
- "target_node_id": "074833b0-e142-4bbc-8dec-209a35e178a3",
336
- "target_handle_id": "6e4af17f-bbee-4777-b10d-af042cd6e16a",
337
- "type": "DEFAULT",
338
- }
339
- ],
340
- "display_data": {"viewport": {"x": 0.0, "y": 0.0, "zoom": 1.0}},
341
- "definition": {
342
- "name": "StackedWorkflow",
343
- "module": [
344
- "vellum_ee",
345
- "workflows",
346
- "display",
347
- "tests",
348
- "workflow_serialization",
349
- "generic_nodes",
350
- "test_adornments_serialization",
309
+ "attributes": [
310
+ {
311
+ "id": "ab2fbab0-e2a0-419b-b1ef-ce11ecf11e90",
312
+ "name": "on_error_code",
313
+ "value": {"type": "CONSTANT_VALUE", "value": {"type": "JSON", "value": None}},
314
+ }
351
315
  ],
352
316
  },
353
- },
354
- "input_variables": [],
355
- "state_variables": [],
356
- "output_variables": [],
317
+ ],
318
+ "attributes": [],
319
+ "outputs": [],
357
320
  },
358
- exec_config,
359
- ignore_order=True,
321
+ inner_stacked_generic_node,
360
322
  )
@@ -54,7 +54,6 @@ def test_serialize_workflow(vellum_client):
54
54
 
55
55
  # AND its raw data should be what we expect
56
56
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
57
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
58
57
  assert len(workflow_raw_data["edges"]) == 4
59
58
  assert len(workflow_raw_data["nodes"]) == 5
60
59
 
@@ -40,7 +40,6 @@ def test_serialize_workflow_with_filepath():
40
40
 
41
41
  # AND its raw data should be what we expect
42
42
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
43
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
44
43
  assert len(workflow_raw_data["edges"]) == 3
45
44
  assert len(workflow_raw_data["nodes"]) == 4
46
45
 
@@ -280,7 +279,6 @@ def test_serialize_workflow_with_code():
280
279
 
281
280
  # AND its raw data should be what we expect
282
281
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
283
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
284
282
  assert len(workflow_raw_data["edges"]) == 3
285
283
  assert len(workflow_raw_data["nodes"]) == 4
286
284
 
@@ -508,7 +506,6 @@ def test_serialize_workflow__try_wrapped():
508
506
 
509
507
  # AND its raw data should be what we expect
510
508
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
511
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
512
509
  assert len(workflow_raw_data["edges"]) == 3
513
510
  assert len(workflow_raw_data["nodes"]) == 4
514
511
 
@@ -95,7 +95,6 @@ def test_serialize_workflow():
95
95
 
96
96
  # AND its raw data should be what we expect
97
97
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
98
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
99
98
  assert len(workflow_raw_data["edges"]) == 11
100
99
  assert len(workflow_raw_data["nodes"]) == 12
101
100
 
@@ -872,7 +871,6 @@ def test_conditional_node_serialize_all_operators_with_lhs_and_rhs(descriptor, o
872
871
 
873
872
  # AND its raw data should be what we expect
874
873
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
875
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
876
874
 
877
875
  # AND the conditional node should be what we expect
878
876
  conditional_node = workflow_raw_data["nodes"][1]
@@ -997,7 +995,6 @@ def test_conditional_node_serialize_all_operators_with_expression(descriptor, op
997
995
 
998
996
  # AND its raw data should be what we expect
999
997
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
1000
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
1001
998
 
1002
999
  # AND the conditional node should be what we expect
1003
1000
  conditional_node = workflow_raw_data["nodes"][1]
@@ -1108,7 +1105,6 @@ def test_conditional_node_serialize_all_operators_with_value_and_start_and_end(d
1108
1105
 
1109
1106
  # AND its raw data should be what we expect
1110
1107
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
1111
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
1112
1108
 
1113
1109
  # AND the conditional node should be what we expect
1114
1110
  conditional_node = workflow_raw_data["nodes"][1]
@@ -77,7 +77,6 @@ def test_serialize_workflow():
77
77
 
78
78
  # AND its raw data should be what we expect
79
79
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
80
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
81
80
  assert len(workflow_raw_data["edges"]) == 3
82
81
  assert len(workflow_raw_data["nodes"]) == 4
83
82
 
@@ -55,7 +55,6 @@ def test_serialize_workflow():
55
55
 
56
56
  # AND its raw data should be what we expect
57
57
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
58
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
59
58
  assert len(workflow_raw_data["edges"]) == 4
60
59
  assert len(workflow_raw_data["nodes"]) == 5
61
60
 
@@ -51,7 +51,6 @@ def test_serialize_workflow():
51
51
 
52
52
  # AND its raw data should be what we expect
53
53
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
54
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
55
54
  assert len(workflow_raw_data["edges"]) == 2
56
55
  assert len(workflow_raw_data["nodes"]) == 3
57
56
 
@@ -53,7 +53,6 @@ def test_serialize_workflow():
53
53
 
54
54
  # AND its raw data is what we expect
55
55
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
56
- assert workflow_raw_data.keys() == {"nodes", "edges", "display_data", "definition"}
57
56
  assert len(workflow_raw_data["nodes"]) == 3
58
57
  assert len(workflow_raw_data["edges"]) == 2
59
58
 
@@ -67,7 +67,6 @@ def test_serialize_workflow():
67
67
 
68
68
  # AND its raw data should be what we expect
69
69
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
70
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
71
70
  assert len(workflow_raw_data["edges"]) == 3
72
71
  assert len(workflow_raw_data["nodes"]) == 4
73
72
 
@@ -283,6 +282,24 @@ def test_serialize_workflow():
283
282
  "name": "NestedWorkflow",
284
283
  "module": ["tests", "workflows", "basic_inline_subworkflow", "workflow"],
285
284
  },
285
+ "output_values": [
286
+ {
287
+ "output_variable_id": "2fc57139-7420-49e5-96a6-dcbb3ff5d622",
288
+ "value": {
289
+ "type": "NODE_OUTPUT",
290
+ "node_id": "1381c078-efa2-4255-89a1-7b4cb742c7fc",
291
+ "node_output_id": "3f4c753e-f057-47bb-9748-7968283cc8aa",
292
+ },
293
+ },
294
+ {
295
+ "output_variable_id": "fad5dd9f-3328-4e70-ad55-65a5325a4a82",
296
+ "value": {
297
+ "type": "NODE_OUTPUT",
298
+ "node_id": "1381c078-efa2-4255-89a1-7b4cb742c7fc",
299
+ "node_output_id": "2a4a62b3-cd26-4d2c-b3f1-eaa5f9dd22dd",
300
+ },
301
+ },
302
+ ],
286
303
  },
287
304
  "input_variables": [{"id": "704c4640-bfda-44f0-8da3-e9cfc4f21cf2", "key": "metro", "type": "STRING"}],
288
305
  "output_variables": [
@@ -302,7 +319,6 @@ def test_serialize_workflow():
302
319
  "ports": [{"id": "cfd831bc-ee7f-44d0-8d76-0ba0cd0277dc", "name": "default", "type": "DEFAULT"}],
303
320
  },
304
321
  subworkflow_node,
305
- ignore_order=True,
306
322
  )
307
323
 
308
324
  temperature_terminal_node = next(
@@ -54,7 +54,6 @@ def test_serialize_workflow():
54
54
 
55
55
  # AND its raw data should be what we expect
56
56
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
57
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
58
57
  assert len(workflow_raw_data["edges"]) == 2
59
58
  assert len(workflow_raw_data["nodes"]) == 3
60
59
 
@@ -235,6 +234,16 @@ def test_serialize_workflow():
235
234
  "workflow",
236
235
  ],
237
236
  },
237
+ "output_values": [
238
+ {
239
+ "output_variable_id": "2a957315-fae0-4366-8a35-f0b315c5eade",
240
+ "value": {
241
+ "type": "NODE_OUTPUT",
242
+ "node_id": "baf6d316-dc75-41e8-96c0-015aede96309",
243
+ "node_output_id": "a7bcb362-a2b8-4476-b0de-a361efeec204",
244
+ },
245
+ }
246
+ ],
238
247
  },
239
248
  "input_variables": [
240
249
  {
@@ -36,7 +36,6 @@ def test_serialize_workflow__await_all():
36
36
 
37
37
  # AND its raw data should be what we expect
38
38
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
39
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
40
39
  assert len(workflow_raw_data["edges"]) == 6
41
40
  assert len(workflow_raw_data["nodes"]) == 6
42
41
 
@@ -74,7 +74,6 @@ def test_serialize_workflow(vellum_client):
74
74
 
75
75
  # AND its raw data should be what we expect
76
76
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
77
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
78
77
  assert len(workflow_raw_data["edges"]) == 2
79
78
  assert len(workflow_raw_data["nodes"]) == 3
80
79
 
@@ -101,7 +100,7 @@ def test_serialize_workflow(vellum_client):
101
100
  "type": "PROMPT",
102
101
  "inputs": [
103
102
  {
104
- "id": "509cf3d4-db72-483e-897a-0f7f20e70d03",
103
+ "id": "947d7ead-0fad-4e5f-aa3a-d06029ac94bc",
105
104
  "key": "city",
106
105
  "value": {
107
106
  "combinator": "OR",
@@ -116,7 +115,7 @@ def test_serialize_workflow(vellum_client):
116
115
  },
117
116
  },
118
117
  {
119
- "id": "7d6ec5ac-c582-4153-bd8a-b8794c367420",
118
+ "id": "3deebdd7-2900-4d8c-93f2-e5b90649ac42",
120
119
  "key": "date",
121
120
  "value": {
122
121
  "combinator": "OR",
@@ -40,7 +40,6 @@ def test_serialize_workflow():
40
40
 
41
41
  # AND its raw data is what we expect
42
42
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
43
- assert workflow_raw_data.keys() == {"nodes", "edges", "display_data", "definition"}
44
43
  assert len(workflow_raw_data["nodes"]) == 3
45
44
  assert len(workflow_raw_data["edges"]) == 2
46
45
 
@@ -83,7 +83,6 @@ def test_serialize_workflow(vellum_client):
83
83
 
84
84
  # AND its raw data should be what we expect
85
85
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
86
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
87
86
  assert len(workflow_raw_data["edges"]) == 3
88
87
  assert len(workflow_raw_data["nodes"]) == 4
89
88
 
@@ -110,7 +109,7 @@ def test_serialize_workflow(vellum_client):
110
109
  "type": "SUBWORKFLOW",
111
110
  "inputs": [
112
111
  {
113
- "id": "dade23b9-dab6-4760-9247-da189f1019d2",
112
+ "id": "be426336-0844-4ebd-8cfe-efef60305b92",
114
113
  "key": "city",
115
114
  "value": {
116
115
  "rules": [
@@ -123,7 +122,7 @@ def test_serialize_workflow(vellum_client):
123
122
  },
124
123
  },
125
124
  {
126
- "id": "8d73270e-2cf9-4146-b053-4780b99857a6",
125
+ "id": "8a7495b1-a7fc-405f-8ef6-ba05dd3f9e5c",
127
126
  "key": "date",
128
127
  "value": {
129
128
  "rules": [
@@ -46,7 +46,6 @@ def test_serialize_workflow():
46
46
 
47
47
  # AND its raw data should be what we expect
48
48
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
49
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
50
49
  assert len(workflow_raw_data["edges"]) == 2
51
50
  assert len(workflow_raw_data["nodes"]) == 3
52
51
 
@@ -44,7 +44,6 @@ def test_serialize_workflow():
44
44
 
45
45
  # AND its raw data should be what we expect
46
46
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
47
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
48
47
  assert len(workflow_raw_data["edges"]) == 1
49
48
  assert len(workflow_raw_data["nodes"]) == 2
50
49
 
@@ -66,7 +65,7 @@ def test_serialize_workflow():
66
65
  "type": "TERMINAL",
67
66
  "data": {
68
67
  "label": "Basic Final Output Node",
69
- "name": "basic-final-output-node",
68
+ "name": "value",
70
69
  "target_handle_id": "0173d3c6-11d1-44b7-b070-ca9ff5119046",
71
70
  "output_id": "aa63e3f6-fde3-4d19-84ef-29982d44d709",
72
71
  "output_type": "STRING",
@@ -47,7 +47,6 @@ def test_serialize_workflow():
47
47
 
48
48
  # AND its raw data should be what we expect
49
49
  workflow_raw_data = serialized_workflow["workflow_raw_data"]
50
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
51
50
  assert len(workflow_raw_data["edges"]) == 3
52
51
  assert len(workflow_raw_data["nodes"]) == 4
53
52
 
@@ -15,41 +15,7 @@ def test_serialize_workflow__missing_final_output_node():
15
15
  # WHEN we serialize it
16
16
  serialized_workflow: dict = workflow_display.serialize()
17
17
 
18
- # THEN we should get a serialized representation of the Workflow
19
- assert serialized_workflow.keys() == {
20
- "workflow_raw_data",
21
- "input_variables",
22
- "state_variables",
23
- "output_variables",
24
- }
25
-
26
- # AND its input variables should be what we expect
27
- input_variables = serialized_workflow["input_variables"]
28
- assert len(input_variables) == 2
29
- assert not DeepDiff(
30
- [
31
- {
32
- "id": "da086239-d743-4246-b666-5c91e22fb88c",
33
- "key": "alpha",
34
- "type": "STRING",
35
- "required": True,
36
- "default": None,
37
- "extensions": {"color": None},
38
- },
39
- {
40
- "id": "a8b6c5d4-a0e9-4457-834b-46b633c466a6",
41
- "key": "beta",
42
- "type": "STRING",
43
- "required": True,
44
- "default": None,
45
- "extensions": {"color": None},
46
- },
47
- ],
48
- input_variables,
49
- ignore_order=True,
50
- )
51
-
52
- # AND its output variables should be what we expect
18
+ # THEN we should get a serialized representation its output variables to be what we expect
53
19
  output_variables = serialized_workflow["output_variables"]
54
20
  assert len(output_variables) == 2
55
21
  assert not DeepDiff(
@@ -61,27 +27,11 @@ def test_serialize_workflow__missing_final_output_node():
61
27
  ignore_order=True,
62
28
  )
63
29
 
64
- # AND its raw data should be what we expect
65
- workflow_raw_data = serialized_workflow["workflow_raw_data"]
66
- assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
67
- assert len(workflow_raw_data["edges"]) == 3
68
- assert len(workflow_raw_data["nodes"]) == 4
69
-
70
30
  # AND each node should be serialized correctly
71
- entrypoint_node = workflow_raw_data["nodes"][0]
72
- assert entrypoint_node == {
73
- "id": "b109349f-ca1b-4a5a-a66e-a1321cf297f7",
74
- "type": "ENTRYPOINT",
75
- "inputs": [],
76
- "data": {"label": "Entrypoint Node", "source_handle_id": "943ac183-d107-4604-aed1-619bd7fef09c"},
77
- "display_data": {"position": {"x": 0.0, "y": 0.0}},
78
- "base": None,
79
- "definition": None,
80
- }
81
-
82
- passthrough_node = next(node for node in workflow_raw_data["nodes"] if node["type"] == "GENERIC")
83
- assert passthrough_node["id"] == "32d88cab-e9fa-4a56-9bc2-fb6e1fd0897f"
31
+ workflow_raw_data = serialized_workflow["workflow_raw_data"]
32
+ assert isinstance(workflow_raw_data, dict)
84
33
 
34
+ # AND we should create synthetic terminal nodes for each output variable
85
35
  final_output_nodes = [node for node in workflow_raw_data["nodes"] if node["type"] == "TERMINAL"]
86
36
  assert not DeepDiff(
87
37
  [
@@ -90,7 +40,7 @@ def test_serialize_workflow__missing_final_output_node():
90
40
  "type": "TERMINAL",
91
41
  "data": {
92
42
  "label": "First Final Output Node",
93
- "name": "first-final-output-node",
43
+ "name": "alpha",
94
44
  "target_handle_id": "a0c2eb7a-398e-4f28-b63d-f3bae9b563ee",
95
45
  "output_id": "0cd02933-c5b9-47c9-aede-e97c5870e8aa",
96
46
  "output_type": "STRING",
@@ -1,11 +1,13 @@
1
1
  from dataclasses import dataclass, field
2
2
  from typing import TYPE_CHECKING, Dict, Tuple, Type
3
3
 
4
+ from vellum.client import Vellum as VellumClient
4
5
  from vellum.workflows.descriptors.base import BaseDescriptor
5
6
  from vellum.workflows.events.workflow import WorkflowEventDisplayContext # noqa: F401
6
7
  from vellum.workflows.nodes import BaseNode
7
8
  from vellum.workflows.ports import Port
8
9
  from vellum.workflows.references import OutputReference, StateValueReference, WorkflowInputReference
10
+ from vellum.workflows.vellum_client import create_vellum_client
9
11
  from vellum.workflows.workflows.base import BaseWorkflow
10
12
  from vellum_ee.workflows.display.base import (
11
13
  EdgeDisplay,
@@ -35,6 +37,7 @@ PortDisplays = Dict[Port, PortDisplay]
35
37
 
36
38
  @dataclass
37
39
  class WorkflowDisplayContext:
40
+ client: VellumClient = field(default_factory=create_vellum_client)
38
41
  workflow_display_class: Type["BaseWorkflowDisplay"] = field(default_factory=get_default_workflow_display_class)
39
42
  workflow_display: WorkflowMetaDisplay = field(default_factory=lambda: WorkflowMetaDisplay.get_default(BaseWorkflow))
40
43
  workflow_input_displays: WorkflowInputsDisplays = field(default_factory=dict)