vellum-ai 0.9.16rc2__py3-none-any.whl → 0.9.16rc4__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (245) hide show
  1. vellum/plugins/__init__.py +0 -0
  2. vellum/plugins/pydantic.py +74 -0
  3. vellum/plugins/utils.py +19 -0
  4. vellum/plugins/vellum_mypy.py +639 -3
  5. vellum/workflows/README.md +90 -0
  6. vellum/workflows/__init__.py +5 -0
  7. vellum/workflows/constants.py +43 -0
  8. vellum/workflows/descriptors/__init__.py +0 -0
  9. vellum/workflows/descriptors/base.py +339 -0
  10. vellum/workflows/descriptors/tests/test_utils.py +83 -0
  11. vellum/workflows/descriptors/utils.py +90 -0
  12. vellum/workflows/edges/__init__.py +5 -0
  13. vellum/workflows/edges/edge.py +23 -0
  14. vellum/workflows/emitters/__init__.py +5 -0
  15. vellum/workflows/emitters/base.py +14 -0
  16. vellum/workflows/environment/__init__.py +5 -0
  17. vellum/workflows/environment/environment.py +7 -0
  18. vellum/workflows/errors/__init__.py +6 -0
  19. vellum/workflows/errors/types.py +20 -0
  20. vellum/workflows/events/__init__.py +31 -0
  21. vellum/workflows/events/node.py +125 -0
  22. vellum/workflows/events/tests/__init__.py +0 -0
  23. vellum/workflows/events/tests/test_event.py +216 -0
  24. vellum/workflows/events/types.py +52 -0
  25. vellum/workflows/events/utils.py +5 -0
  26. vellum/workflows/events/workflow.py +139 -0
  27. vellum/workflows/exceptions.py +15 -0
  28. vellum/workflows/expressions/__init__.py +0 -0
  29. vellum/workflows/expressions/accessor.py +52 -0
  30. vellum/workflows/expressions/and_.py +32 -0
  31. vellum/workflows/expressions/begins_with.py +31 -0
  32. vellum/workflows/expressions/between.py +38 -0
  33. vellum/workflows/expressions/coalesce_expression.py +41 -0
  34. vellum/workflows/expressions/contains.py +30 -0
  35. vellum/workflows/expressions/does_not_begin_with.py +31 -0
  36. vellum/workflows/expressions/does_not_contain.py +30 -0
  37. vellum/workflows/expressions/does_not_end_with.py +31 -0
  38. vellum/workflows/expressions/does_not_equal.py +25 -0
  39. vellum/workflows/expressions/ends_with.py +31 -0
  40. vellum/workflows/expressions/equals.py +25 -0
  41. vellum/workflows/expressions/greater_than.py +33 -0
  42. vellum/workflows/expressions/greater_than_or_equal_to.py +33 -0
  43. vellum/workflows/expressions/in_.py +31 -0
  44. vellum/workflows/expressions/is_blank.py +24 -0
  45. vellum/workflows/expressions/is_not_blank.py +24 -0
  46. vellum/workflows/expressions/is_not_null.py +21 -0
  47. vellum/workflows/expressions/is_not_undefined.py +22 -0
  48. vellum/workflows/expressions/is_null.py +21 -0
  49. vellum/workflows/expressions/is_undefined.py +22 -0
  50. vellum/workflows/expressions/less_than.py +33 -0
  51. vellum/workflows/expressions/less_than_or_equal_to.py +33 -0
  52. vellum/workflows/expressions/not_between.py +38 -0
  53. vellum/workflows/expressions/not_in.py +31 -0
  54. vellum/workflows/expressions/or_.py +32 -0
  55. vellum/workflows/graph/__init__.py +3 -0
  56. vellum/workflows/graph/graph.py +131 -0
  57. vellum/workflows/graph/tests/__init__.py +0 -0
  58. vellum/workflows/graph/tests/test_graph.py +437 -0
  59. vellum/workflows/inputs/__init__.py +5 -0
  60. vellum/workflows/inputs/base.py +55 -0
  61. vellum/workflows/logging.py +14 -0
  62. vellum/workflows/nodes/__init__.py +46 -0
  63. vellum/workflows/nodes/bases/__init__.py +7 -0
  64. vellum/workflows/nodes/bases/base.py +332 -0
  65. vellum/workflows/nodes/bases/base_subworkflow_node/__init__.py +5 -0
  66. vellum/workflows/nodes/bases/base_subworkflow_node/node.py +10 -0
  67. vellum/workflows/nodes/bases/tests/__init__.py +0 -0
  68. vellum/workflows/nodes/bases/tests/test_base_node.py +125 -0
  69. vellum/workflows/nodes/core/__init__.py +16 -0
  70. vellum/workflows/nodes/core/error_node/__init__.py +5 -0
  71. vellum/workflows/nodes/core/error_node/node.py +26 -0
  72. vellum/workflows/nodes/core/inline_subworkflow_node/__init__.py +5 -0
  73. vellum/workflows/nodes/core/inline_subworkflow_node/node.py +73 -0
  74. vellum/workflows/nodes/core/map_node/__init__.py +5 -0
  75. vellum/workflows/nodes/core/map_node/node.py +147 -0
  76. vellum/workflows/nodes/core/map_node/tests/__init__.py +0 -0
  77. vellum/workflows/nodes/core/map_node/tests/test_node.py +65 -0
  78. vellum/workflows/nodes/core/retry_node/__init__.py +5 -0
  79. vellum/workflows/nodes/core/retry_node/node.py +106 -0
  80. vellum/workflows/nodes/core/retry_node/tests/__init__.py +0 -0
  81. vellum/workflows/nodes/core/retry_node/tests/test_node.py +93 -0
  82. vellum/workflows/nodes/core/templating_node/__init__.py +5 -0
  83. vellum/workflows/nodes/core/templating_node/custom_filters.py +12 -0
  84. vellum/workflows/nodes/core/templating_node/exceptions.py +2 -0
  85. vellum/workflows/nodes/core/templating_node/node.py +123 -0
  86. vellum/workflows/nodes/core/templating_node/render.py +55 -0
  87. vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py +21 -0
  88. vellum/workflows/nodes/core/try_node/__init__.py +5 -0
  89. vellum/workflows/nodes/core/try_node/node.py +110 -0
  90. vellum/workflows/nodes/core/try_node/tests/__init__.py +0 -0
  91. vellum/workflows/nodes/core/try_node/tests/test_node.py +82 -0
  92. vellum/workflows/nodes/displayable/__init__.py +31 -0
  93. vellum/workflows/nodes/displayable/api_node/__init__.py +5 -0
  94. vellum/workflows/nodes/displayable/api_node/node.py +44 -0
  95. vellum/workflows/nodes/displayable/bases/__init__.py +11 -0
  96. vellum/workflows/nodes/displayable/bases/api_node/__init__.py +5 -0
  97. vellum/workflows/nodes/displayable/bases/api_node/node.py +70 -0
  98. vellum/workflows/nodes/displayable/bases/base_prompt_node/__init__.py +5 -0
  99. vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py +60 -0
  100. vellum/workflows/nodes/displayable/bases/inline_prompt_node/__init__.py +5 -0
  101. vellum/workflows/nodes/displayable/bases/inline_prompt_node/constants.py +13 -0
  102. vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py +118 -0
  103. vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +98 -0
  104. vellum/workflows/nodes/displayable/bases/search_node.py +90 -0
  105. vellum/workflows/nodes/displayable/code_execution_node/__init__.py +5 -0
  106. vellum/workflows/nodes/displayable/code_execution_node/node.py +197 -0
  107. vellum/workflows/nodes/displayable/code_execution_node/tests/__init__.py +0 -0
  108. vellum/workflows/nodes/displayable/code_execution_node/tests/fixtures/__init__.py +0 -0
  109. vellum/workflows/nodes/displayable/code_execution_node/tests/fixtures/main.py +3 -0
  110. vellum/workflows/nodes/displayable/code_execution_node/tests/test_code_execution_node.py +111 -0
  111. vellum/workflows/nodes/displayable/code_execution_node/utils.py +10 -0
  112. vellum/workflows/nodes/displayable/conditional_node/__init__.py +5 -0
  113. vellum/workflows/nodes/displayable/conditional_node/node.py +25 -0
  114. vellum/workflows/nodes/displayable/final_output_node/__init__.py +5 -0
  115. vellum/workflows/nodes/displayable/final_output_node/node.py +43 -0
  116. vellum/workflows/nodes/displayable/guardrail_node/__init__.py +5 -0
  117. vellum/workflows/nodes/displayable/guardrail_node/node.py +97 -0
  118. vellum/workflows/nodes/displayable/inline_prompt_node/__init__.py +5 -0
  119. vellum/workflows/nodes/displayable/inline_prompt_node/node.py +41 -0
  120. vellum/workflows/nodes/displayable/merge_node/__init__.py +5 -0
  121. vellum/workflows/nodes/displayable/merge_node/node.py +10 -0
  122. vellum/workflows/nodes/displayable/prompt_deployment_node/__init__.py +5 -0
  123. vellum/workflows/nodes/displayable/prompt_deployment_node/node.py +45 -0
  124. vellum/workflows/nodes/displayable/search_node/__init__.py +5 -0
  125. vellum/workflows/nodes/displayable/search_node/node.py +26 -0
  126. vellum/workflows/nodes/displayable/subworkflow_deployment_node/__init__.py +5 -0
  127. vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +156 -0
  128. vellum/workflows/nodes/displayable/tests/__init__.py +0 -0
  129. vellum/workflows/nodes/displayable/tests/test_inline_text_prompt_node.py +148 -0
  130. vellum/workflows/nodes/displayable/tests/test_search_node_wth_text_output.py +134 -0
  131. vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py +80 -0
  132. vellum/workflows/nodes/utils.py +27 -0
  133. vellum/workflows/outputs/__init__.py +6 -0
  134. vellum/workflows/outputs/base.py +196 -0
  135. vellum/workflows/ports/__init__.py +7 -0
  136. vellum/workflows/ports/node_ports.py +75 -0
  137. vellum/workflows/ports/port.py +75 -0
  138. vellum/workflows/ports/utils.py +40 -0
  139. vellum/workflows/references/__init__.py +17 -0
  140. vellum/workflows/references/environment_variable.py +20 -0
  141. vellum/workflows/references/execution_count.py +20 -0
  142. vellum/workflows/references/external_input.py +49 -0
  143. vellum/workflows/references/input.py +7 -0
  144. vellum/workflows/references/lazy.py +55 -0
  145. vellum/workflows/references/node.py +43 -0
  146. vellum/workflows/references/output.py +78 -0
  147. vellum/workflows/references/state_value.py +23 -0
  148. vellum/workflows/references/vellum_secret.py +15 -0
  149. vellum/workflows/references/workflow_input.py +41 -0
  150. vellum/workflows/resolvers/__init__.py +5 -0
  151. vellum/workflows/resolvers/base.py +15 -0
  152. vellum/workflows/runner/__init__.py +5 -0
  153. vellum/workflows/runner/runner.py +588 -0
  154. vellum/workflows/runner/types.py +18 -0
  155. vellum/workflows/state/__init__.py +5 -0
  156. vellum/workflows/state/base.py +327 -0
  157. vellum/workflows/state/context.py +18 -0
  158. vellum/workflows/state/encoder.py +57 -0
  159. vellum/workflows/state/store.py +28 -0
  160. vellum/workflows/state/tests/__init__.py +0 -0
  161. vellum/workflows/state/tests/test_state.py +113 -0
  162. vellum/workflows/types/__init__.py +0 -0
  163. vellum/workflows/types/core.py +91 -0
  164. vellum/workflows/types/generics.py +14 -0
  165. vellum/workflows/types/stack.py +39 -0
  166. vellum/workflows/types/tests/__init__.py +0 -0
  167. vellum/workflows/types/tests/test_utils.py +76 -0
  168. vellum/workflows/types/utils.py +164 -0
  169. vellum/workflows/utils/__init__.py +0 -0
  170. vellum/workflows/utils/names.py +13 -0
  171. vellum/workflows/utils/tests/__init__.py +0 -0
  172. vellum/workflows/utils/tests/test_names.py +15 -0
  173. vellum/workflows/utils/tests/test_vellum_variables.py +25 -0
  174. vellum/workflows/utils/vellum_variables.py +81 -0
  175. vellum/workflows/vellum_client.py +18 -0
  176. vellum/workflows/workflows/__init__.py +5 -0
  177. vellum/workflows/workflows/base.py +365 -0
  178. {vellum_ai-0.9.16rc2.dist-info → vellum_ai-0.9.16rc4.dist-info}/METADATA +2 -1
  179. {vellum_ai-0.9.16rc2.dist-info → vellum_ai-0.9.16rc4.dist-info}/RECORD +245 -7
  180. vellum_cli/__init__.py +72 -0
  181. vellum_cli/aliased_group.py +103 -0
  182. vellum_cli/config.py +96 -0
  183. vellum_cli/image_push.py +112 -0
  184. vellum_cli/logger.py +36 -0
  185. vellum_cli/pull.py +73 -0
  186. vellum_cli/push.py +121 -0
  187. vellum_cli/tests/test_config.py +100 -0
  188. vellum_cli/tests/test_pull.py +152 -0
  189. vellum_ee/workflows/__init__.py +0 -0
  190. vellum_ee/workflows/display/__init__.py +0 -0
  191. vellum_ee/workflows/display/base.py +73 -0
  192. vellum_ee/workflows/display/nodes/__init__.py +4 -0
  193. vellum_ee/workflows/display/nodes/base_node_display.py +116 -0
  194. vellum_ee/workflows/display/nodes/base_node_vellum_display.py +36 -0
  195. vellum_ee/workflows/display/nodes/get_node_display_class.py +25 -0
  196. vellum_ee/workflows/display/nodes/tests/__init__.py +0 -0
  197. vellum_ee/workflows/display/nodes/tests/test_base_node_display.py +47 -0
  198. vellum_ee/workflows/display/nodes/types.py +18 -0
  199. vellum_ee/workflows/display/nodes/utils.py +33 -0
  200. vellum_ee/workflows/display/nodes/vellum/__init__.py +32 -0
  201. vellum_ee/workflows/display/nodes/vellum/api_node.py +205 -0
  202. vellum_ee/workflows/display/nodes/vellum/code_execution_node.py +71 -0
  203. vellum_ee/workflows/display/nodes/vellum/conditional_node.py +217 -0
  204. vellum_ee/workflows/display/nodes/vellum/final_output_node.py +61 -0
  205. vellum_ee/workflows/display/nodes/vellum/guardrail_node.py +49 -0
  206. vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py +170 -0
  207. vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py +99 -0
  208. vellum_ee/workflows/display/nodes/vellum/map_node.py +100 -0
  209. vellum_ee/workflows/display/nodes/vellum/merge_node.py +48 -0
  210. vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py +68 -0
  211. vellum_ee/workflows/display/nodes/vellum/search_node.py +193 -0
  212. vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py +58 -0
  213. vellum_ee/workflows/display/nodes/vellum/templating_node.py +67 -0
  214. vellum_ee/workflows/display/nodes/vellum/tests/__init__.py +0 -0
  215. vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py +106 -0
  216. vellum_ee/workflows/display/nodes/vellum/try_node.py +38 -0
  217. vellum_ee/workflows/display/nodes/vellum/utils.py +76 -0
  218. vellum_ee/workflows/display/tests/__init__.py +0 -0
  219. vellum_ee/workflows/display/tests/workflow_serialization/__init__.py +0 -0
  220. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py +426 -0
  221. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +607 -0
  222. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +1175 -0
  223. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py +235 -0
  224. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +511 -0
  225. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +372 -0
  226. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +272 -0
  227. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py +289 -0
  228. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py +354 -0
  229. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py +123 -0
  230. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py +84 -0
  231. vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py +233 -0
  232. vellum_ee/workflows/display/types.py +46 -0
  233. vellum_ee/workflows/display/utils/__init__.py +0 -0
  234. vellum_ee/workflows/display/utils/tests/__init__.py +0 -0
  235. vellum_ee/workflows/display/utils/tests/test_uuids.py +16 -0
  236. vellum_ee/workflows/display/utils/uuids.py +24 -0
  237. vellum_ee/workflows/display/utils/vellum.py +121 -0
  238. vellum_ee/workflows/display/vellum.py +357 -0
  239. vellum_ee/workflows/display/workflows/__init__.py +5 -0
  240. vellum_ee/workflows/display/workflows/base_workflow_display.py +302 -0
  241. vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py +32 -0
  242. vellum_ee/workflows/display/workflows/vellum_workflow_display.py +386 -0
  243. {vellum_ai-0.9.16rc2.dist-info → vellum_ai-0.9.16rc4.dist-info}/LICENSE +0 -0
  244. {vellum_ai-0.9.16rc2.dist-info → vellum_ai-0.9.16rc4.dist-info}/WHEEL +0 -0
  245. {vellum_ai-0.9.16rc2.dist-info → vellum_ai-0.9.16rc4.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,372 @@
1
+ from unittest import mock
2
+
3
+ from deepdiff import DeepDiff
4
+
5
+ from tests.workflows.basic_map_node.workflow import SimpleMapExample
6
+ from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
7
+ from vellum_ee.workflows.display.workflows import VellumWorkflowDisplay
8
+ from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
9
+
10
+
11
+ def test_serialize_workflow():
12
+ # GIVEN a Workflow that uses a MapNode
13
+ # WHEN we serialize it
14
+ workflow_display = get_workflow_display(base_display_class=VellumWorkflowDisplay, workflow_class=SimpleMapExample)
15
+
16
+ # TODO: Support serialization of BaseNode
17
+ # https://app.shortcut.com/vellum/story/4871/support-serialization-of-base-node
18
+ with mock.patch.object(BaseNodeVellumDisplay, "serialize") as mocked_serialize:
19
+ mocked_serialize.return_value = {"type": "MOCKED"}
20
+ serialized_workflow: dict = workflow_display.serialize()
21
+
22
+ # THEN we should get a serialized representation of the Workflow
23
+ assert serialized_workflow.keys() == {
24
+ "workflow_raw_data",
25
+ "input_variables",
26
+ "output_variables",
27
+ }
28
+
29
+ # AND its input variables should be what we expect
30
+ input_variables = serialized_workflow["input_variables"]
31
+ assert len(input_variables) == 1
32
+ assert not DeepDiff(
33
+ [
34
+ {
35
+ "id": "db2eb237-38e4-417a-8bfc-5bda0f3165ca",
36
+ "key": "fruits",
37
+ "type": "JSON",
38
+ "required": None,
39
+ "default": None,
40
+ "extensions": None,
41
+ },
42
+ ],
43
+ input_variables,
44
+ ignore_order=True,
45
+ )
46
+
47
+ # AND its output variables should be what we expect
48
+ output_variables = serialized_workflow["output_variables"]
49
+ assert len(output_variables) == 1
50
+ assert not DeepDiff(
51
+ [
52
+ {
53
+ "id": "145b0b68-224b-4f83-90e6-eea3457e6c3e",
54
+ "key": "final_value",
55
+ "type": "JSON",
56
+ },
57
+ ],
58
+ output_variables,
59
+ ignore_order=True,
60
+ )
61
+
62
+ # AND its raw data should be what we expect
63
+ workflow_raw_data = serialized_workflow["workflow_raw_data"]
64
+ assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
65
+ assert len(workflow_raw_data["edges"]) == 2
66
+ assert len(workflow_raw_data["nodes"]) == 3
67
+
68
+ # AND each node should be serialized correctly
69
+ entrypoint_node = workflow_raw_data["nodes"][0]
70
+ assert entrypoint_node == {
71
+ "id": "c0aa464d-1685-4f15-a051-31b426fec92e",
72
+ "type": "ENTRYPOINT",
73
+ "inputs": [],
74
+ "data": {
75
+ "label": "Entrypoint Node",
76
+ "source_handle_id": "844d992e-60ab-4af2-a8ff-52cd858386f7",
77
+ },
78
+ "definition": {
79
+ "bases": [],
80
+ "module": [
81
+ "vellum",
82
+ "workflows",
83
+ "nodes",
84
+ "bases",
85
+ "base",
86
+ ],
87
+ "name": "BaseNode",
88
+ },
89
+ "display_data": {
90
+ "position": {"x": 0.0, "y": 0.0},
91
+ },
92
+ }
93
+
94
+ map_node = workflow_raw_data["nodes"][1]
95
+ assert not DeepDiff(
96
+ {
97
+ "id": "bf83099a-40df-4445-b90d-1f6f1067ebe3",
98
+ "type": "MAP",
99
+ "inputs": [
100
+ {
101
+ "id": "4c0a109f-599e-4d04-a396-a51474fc2996",
102
+ "key": "items",
103
+ "value": {
104
+ "rules": [
105
+ {
106
+ "type": "INPUT_VARIABLE",
107
+ "data": {"input_variable_id": "db2eb237-38e4-417a-8bfc-5bda0f3165ca"},
108
+ }
109
+ ],
110
+ "combinator": "OR",
111
+ },
112
+ }
113
+ ],
114
+ "data": {
115
+ "label": "Map Fruits Node",
116
+ "error_output_id": None,
117
+ "source_handle_id": "a2171a61-0657-43ad-b6d9-cf93ce3270d0",
118
+ "target_handle_id": "b5e8182e-20c5-482b-b4c5-4dde48c01472",
119
+ "variant": "INLINE",
120
+ "workflow_raw_data": {
121
+ "nodes": [
122
+ {
123
+ "id": "ff9bfe6e-839d-4d40-b8fc-313b3bbd0ab0",
124
+ "type": "ENTRYPOINT",
125
+ "inputs": [],
126
+ "data": {
127
+ "label": "Entrypoint Node",
128
+ "source_handle_id": "520d3616-8369-4e79-9da5-3febae299c2a",
129
+ },
130
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
131
+ "definition": {
132
+ "name": "BaseNode",
133
+ "module": [
134
+ "vellum",
135
+ "workflows",
136
+ "nodes",
137
+ "bases",
138
+ "base",
139
+ ],
140
+ "bases": [],
141
+ },
142
+ },
143
+ {"type": "MOCKED"},
144
+ {
145
+ "id": "6f4883b2-70b1-4e1c-ae15-7d0f5aec810b",
146
+ "type": "TERMINAL",
147
+ "data": {
148
+ "label": "Final Output",
149
+ "name": "count",
150
+ "target_handle_id": "9d74571f-b7f5-4c1d-8b7c-b9c648738a4d",
151
+ "output_id": "2a957315-fae0-4366-8a35-f0b315c5eade",
152
+ "output_type": "NUMBER",
153
+ "node_input_id": "ae65cf7e-3db6-410f-a556-75ee11ce7e84",
154
+ },
155
+ "inputs": [
156
+ {
157
+ "id": "ae65cf7e-3db6-410f-a556-75ee11ce7e84",
158
+ "key": "node_input",
159
+ "value": {
160
+ "rules": [
161
+ {
162
+ "type": "NODE_OUTPUT",
163
+ "data": {
164
+ "node_id": "baf6d316-dc75-41e8-96c0-015aede96309",
165
+ "output_id": "a7bcb362-a2b8-4476-b0de-a361efeec204",
166
+ },
167
+ }
168
+ ],
169
+ "combinator": "OR",
170
+ },
171
+ }
172
+ ],
173
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
174
+ "definition": {
175
+ "name": "FinalOutputNode",
176
+ "module": [
177
+ "vellum",
178
+ "workflows",
179
+ "nodes",
180
+ "displayable",
181
+ "final_output_node",
182
+ "node",
183
+ ],
184
+ "bases": [
185
+ {
186
+ "name": "BaseNode",
187
+ "module": [
188
+ "vellum",
189
+ "workflows",
190
+ "nodes",
191
+ "bases",
192
+ "base",
193
+ ],
194
+ "bases": [],
195
+ }
196
+ ],
197
+ },
198
+ },
199
+ ],
200
+ "edges": [
201
+ {
202
+ "id": "b59c050b-0f6a-4153-ab58-fa051222fa05",
203
+ "source_node_id": "ff9bfe6e-839d-4d40-b8fc-313b3bbd0ab0",
204
+ "source_handle_id": "520d3616-8369-4e79-9da5-3febae299c2a",
205
+ "target_node_id": "baf6d316-dc75-41e8-96c0-015aede96309",
206
+ "target_handle_id": "551d5528-f4e1-42ea-bde0-9de4b4968253",
207
+ "type": "DEFAULT",
208
+ },
209
+ {
210
+ "id": "14152688-6996-4d64-9231-a6e66a4827eb",
211
+ "source_node_id": "baf6d316-dc75-41e8-96c0-015aede96309",
212
+ "source_handle_id": "71ada606-d791-4a59-a252-0795c5faeeaf",
213
+ "target_node_id": "6f4883b2-70b1-4e1c-ae15-7d0f5aec810b",
214
+ "target_handle_id": "9d74571f-b7f5-4c1d-8b7c-b9c648738a4d",
215
+ "type": "DEFAULT",
216
+ },
217
+ ],
218
+ "display_data": {"viewport": {"x": 0.0, "y": 0.0, "zoom": 1.0}},
219
+ "definition": {
220
+ "name": "IterationSubworkflow",
221
+ "module": [
222
+ "tests",
223
+ "workflows",
224
+ "basic_map_node",
225
+ "workflow",
226
+ ],
227
+ },
228
+ },
229
+ "input_variables": [
230
+ {"id": "0fe9dff5-7595-4ff3-a420-416f3fc6f809", "key": "item", "type": "JSON"},
231
+ {"id": "27dfe8ba-8be7-4de9-a930-2ec3e375b149", "key": "index", "type": "NUMBER"},
232
+ {"id": "4c0a109f-599e-4d04-a396-a51474fc2996", "key": "items", "type": "JSON"},
233
+ ],
234
+ "output_variables": [{"id": "56b34d4a-d3a6-4bdb-80a4-dbf644791274", "key": "count", "type": "NUMBER"}],
235
+ "concurrency": None,
236
+ "items_input_id": "4c0a109f-599e-4d04-a396-a51474fc2996",
237
+ "item_input_id": "0fe9dff5-7595-4ff3-a420-416f3fc6f809",
238
+ "index_input_id": "27dfe8ba-8be7-4de9-a930-2ec3e375b149",
239
+ },
240
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
241
+ "definition": {
242
+ "name": "MapFruitsNode",
243
+ "module": [
244
+ "tests",
245
+ "workflows",
246
+ "basic_map_node",
247
+ "workflow",
248
+ ],
249
+ "bases": [
250
+ {
251
+ "name": "MapNode",
252
+ "module": [
253
+ "vellum",
254
+ "workflows",
255
+ "nodes",
256
+ "core",
257
+ "map_node",
258
+ "node",
259
+ ],
260
+ }
261
+ ],
262
+ },
263
+ },
264
+ map_node,
265
+ ignore_order=True,
266
+ )
267
+
268
+ assert not DeepDiff(
269
+ {
270
+ "id": "bacc5d55-07d4-4a0a-a69e-831524480de5",
271
+ "type": "TERMINAL",
272
+ "data": {
273
+ "label": "Final Output",
274
+ "name": "final_value",
275
+ "target_handle_id": "720dd872-2f3d-47b9-8245-89387f04f300",
276
+ "output_id": "145b0b68-224b-4f83-90e6-eea3457e6c3e",
277
+ "output_type": "JSON",
278
+ "node_input_id": "d1b01eac-23a9-43ce-beb3-e13f83bd7d18",
279
+ },
280
+ "inputs": [
281
+ {
282
+ "id": "d1b01eac-23a9-43ce-beb3-e13f83bd7d18",
283
+ "key": "node_input",
284
+ "value": {
285
+ "rules": [
286
+ {
287
+ "type": "NODE_OUTPUT",
288
+ "data": {
289
+ "node_id": "bf83099a-40df-4445-b90d-1f6f1067ebe3",
290
+ "output_id": "56b34d4a-d3a6-4bdb-80a4-dbf644791274",
291
+ },
292
+ }
293
+ ],
294
+ "combinator": "OR",
295
+ },
296
+ }
297
+ ],
298
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
299
+ "definition": {
300
+ "bases": [
301
+ {
302
+ "bases": [],
303
+ "module": [
304
+ "vellum",
305
+ "workflows",
306
+ "nodes",
307
+ "bases",
308
+ "base",
309
+ ],
310
+ "name": "BaseNode",
311
+ },
312
+ ],
313
+ "module": [
314
+ "vellum",
315
+ "workflows",
316
+ "nodes",
317
+ "displayable",
318
+ "final_output_node",
319
+ "node",
320
+ ],
321
+ "name": "FinalOutputNode",
322
+ },
323
+ },
324
+ workflow_raw_data["nodes"][2],
325
+ )
326
+
327
+ # AND each edge should be serialized correctly
328
+ serialized_edges = workflow_raw_data["edges"]
329
+ assert not DeepDiff(
330
+ [
331
+ {
332
+ "id": "f39477f3-445a-412e-a8ab-371baa8ae990",
333
+ "source_node_id": "c0aa464d-1685-4f15-a051-31b426fec92e",
334
+ "source_handle_id": "844d992e-60ab-4af2-a8ff-52cd858386f7",
335
+ "target_node_id": "bf83099a-40df-4445-b90d-1f6f1067ebe3",
336
+ "target_handle_id": "b5e8182e-20c5-482b-b4c5-4dde48c01472",
337
+ "type": "DEFAULT",
338
+ },
339
+ {
340
+ "id": "47a34f6e-d139-4702-aa46-6212bb8a150f",
341
+ "source_node_id": "bf83099a-40df-4445-b90d-1f6f1067ebe3",
342
+ "source_handle_id": "a2171a61-0657-43ad-b6d9-cf93ce3270d0",
343
+ "target_node_id": "bacc5d55-07d4-4a0a-a69e-831524480de5",
344
+ "target_handle_id": "720dd872-2f3d-47b9-8245-89387f04f300",
345
+ "type": "DEFAULT",
346
+ },
347
+ ],
348
+ serialized_edges,
349
+ ignore_order=True,
350
+ )
351
+
352
+ # AND the display data should be what we expect
353
+ display_data = workflow_raw_data["display_data"]
354
+ assert display_data == {
355
+ "viewport": {
356
+ "x": 0.0,
357
+ "y": 0.0,
358
+ "zoom": 1.0,
359
+ }
360
+ }
361
+
362
+ # AND the definition should be what we expect
363
+ definition = workflow_raw_data["definition"]
364
+ assert definition == {
365
+ "name": "SimpleMapExample",
366
+ "module": [
367
+ "tests",
368
+ "workflows",
369
+ "basic_map_node",
370
+ "workflow",
371
+ ],
372
+ }
@@ -0,0 +1,272 @@
1
+ from unittest import mock
2
+
3
+ from deepdiff import DeepDiff
4
+
5
+ from tests.workflows.basic_merge_node.await_all_workflow import AwaitAllPassingWorkflow
6
+ from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
7
+ from vellum_ee.workflows.display.workflows import VellumWorkflowDisplay
8
+ from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
9
+
10
+
11
+ def test_serialize_workflow__await_all():
12
+ # GIVEN a Workflow that uses an await all merge node
13
+ # WHEN we serialize it
14
+ workflow_display = get_workflow_display(
15
+ base_display_class=VellumWorkflowDisplay, workflow_class=AwaitAllPassingWorkflow
16
+ )
17
+
18
+ # TODO: Support serialization of BaseNode
19
+ # https://app.shortcut.com/vellum/story/4871/support-serialization-of-base-node
20
+ with mock.patch.object(BaseNodeVellumDisplay, "serialize") as mocked_serialize:
21
+ mocked_serialize.return_value = {"type": "MOCKED"}
22
+ serialized_workflow: dict = workflow_display.serialize()
23
+
24
+ # THEN we should get a serialized representation of the Workflow
25
+ assert serialized_workflow.keys() == {
26
+ "workflow_raw_data",
27
+ "input_variables",
28
+ "output_variables",
29
+ }
30
+
31
+ # AND its input variables should be what we expect
32
+ input_variables = serialized_workflow["input_variables"]
33
+ assert len(input_variables) == 0
34
+
35
+ # AND its output variables should be what we expect
36
+ output_variables = serialized_workflow["output_variables"]
37
+ assert len(output_variables) == 1
38
+ assert not DeepDiff(
39
+ [
40
+ {"id": "959ba00d-d30b-402e-8676-76efc4c3d2ae", "key": "value", "type": "STRING"},
41
+ ],
42
+ output_variables,
43
+ ignore_order=True,
44
+ )
45
+
46
+ # AND its raw data should be what we expect
47
+ workflow_raw_data = serialized_workflow["workflow_raw_data"]
48
+ assert workflow_raw_data.keys() == {"edges", "nodes", "display_data", "definition"}
49
+ assert len(workflow_raw_data["edges"]) == 6
50
+ assert len(workflow_raw_data["nodes"]) == 6
51
+
52
+ # AND each node should be serialized correctly
53
+ entrypoint_node = next(node for node in workflow_raw_data["nodes"] if node["type"] == "ENTRYPOINT")
54
+ assert entrypoint_node == {
55
+ "id": "dc8aecd0-49ba-4464-a45f-29d3bfd686e4",
56
+ "type": "ENTRYPOINT",
57
+ "definition": {
58
+ "bases": [],
59
+ "module": [
60
+ "vellum",
61
+ "workflows",
62
+ "nodes",
63
+ "bases",
64
+ "base",
65
+ ],
66
+ "name": "BaseNode",
67
+ },
68
+ "inputs": [],
69
+ "data": {
70
+ "label": "Entrypoint Node",
71
+ "source_handle_id": "017d40f5-8326-4e42-a409-b08995defaa8",
72
+ },
73
+ "display_data": {
74
+ "position": {"x": 0.0, "y": 0.0},
75
+ },
76
+ }
77
+
78
+ passthrough_nodes = [node for node in workflow_raw_data["nodes"] if node["type"] == "MOCKED"]
79
+ assert not DeepDiff(
80
+ [
81
+ {
82
+ "type": "MOCKED",
83
+ },
84
+ {
85
+ "type": "MOCKED",
86
+ },
87
+ {
88
+ "type": "MOCKED",
89
+ },
90
+ ],
91
+ passthrough_nodes,
92
+ ignore_order=True,
93
+ )
94
+
95
+ merge_node = next(node for node in workflow_raw_data["nodes"] if node["type"] == "MERGE")
96
+ assert not DeepDiff(
97
+ {
98
+ "id": "37c10e8a-771b-432b-a767-31f5007851f0",
99
+ "type": "MERGE",
100
+ "inputs": [],
101
+ "data": {
102
+ "label": "Await All Merge Node",
103
+ "merge_strategy": "AWAIT_ALL",
104
+ "target_handles": [
105
+ {"id": "f40ff7fb-de1b-4aa4-ba3c-7630f7357cbf"},
106
+ {"id": "42eeb66c-9792-4609-8c71-3a56f668f4dc"},
107
+ ],
108
+ "source_handle_id": "3bbc469f-0fb0-4b3d-a28b-746fefec2818",
109
+ },
110
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
111
+ "definition": {
112
+ "bases": [
113
+ {
114
+ "module": [
115
+ "vellum",
116
+ "workflows",
117
+ "nodes",
118
+ "displayable",
119
+ "merge_node",
120
+ "node",
121
+ ],
122
+ "name": "MergeNode",
123
+ }
124
+ ],
125
+ "module": [
126
+ "tests",
127
+ "workflows",
128
+ "basic_merge_node",
129
+ "await_all_workflow",
130
+ ],
131
+ "name": "AwaitAllMergeNode",
132
+ },
133
+ },
134
+ merge_node,
135
+ ignore_order_func=lambda x: x.path() == "root['data']['target_handles']",
136
+ )
137
+
138
+ final_output_node = next(node for node in workflow_raw_data["nodes"] if node["type"] == "TERMINAL")
139
+ assert final_output_node == {
140
+ "id": "8187ce10-62b7-4a2c-8c0f-297387915467",
141
+ "type": "TERMINAL",
142
+ "data": {
143
+ "label": "Final Output",
144
+ "name": "value",
145
+ "target_handle_id": "ff55701c-16d3-4348-a633-6a298e71377d",
146
+ "output_id": "959ba00d-d30b-402e-8676-76efc4c3d2ae",
147
+ "output_type": "STRING",
148
+ "node_input_id": "7f950be4-2fab-44e0-87a3-b1631aadd0e3",
149
+ },
150
+ "definition": {
151
+ "bases": [
152
+ {
153
+ "bases": [],
154
+ "module": [
155
+ "vellum",
156
+ "workflows",
157
+ "nodes",
158
+ "bases",
159
+ "base",
160
+ ],
161
+ "name": "BaseNode",
162
+ },
163
+ ],
164
+ "module": [
165
+ "vellum",
166
+ "workflows",
167
+ "nodes",
168
+ "displayable",
169
+ "final_output_node",
170
+ "node",
171
+ ],
172
+ "name": "FinalOutputNode",
173
+ },
174
+ "inputs": [
175
+ {
176
+ "id": "7f950be4-2fab-44e0-87a3-b1631aadd0e3",
177
+ "key": "node_input",
178
+ "value": {
179
+ "rules": [
180
+ {
181
+ "type": "NODE_OUTPUT",
182
+ "data": {
183
+ "node_id": "634f0202-9ea9-4c62-b152-1a58c595cffb",
184
+ "output_id": "d4266640-9718-4a74-b24b-500448d87871",
185
+ },
186
+ }
187
+ ],
188
+ "combinator": "OR",
189
+ },
190
+ }
191
+ ],
192
+ "display_data": {"position": {"x": 0.0, "y": 0.0}},
193
+ }
194
+
195
+ # AND each edge should be serialized correctly
196
+ serialized_edges = workflow_raw_data["edges"]
197
+ assert not DeepDiff(
198
+ [
199
+ {
200
+ "id": "9a65dd52-c3eb-496e-9d34-46b39534a261",
201
+ "source_node_id": "dc8aecd0-49ba-4464-a45f-29d3bfd686e4",
202
+ "source_handle_id": "017d40f5-8326-4e42-a409-b08995defaa8",
203
+ "target_node_id": "59243c65-053f-4ea6-9157-3f3edb1477bf",
204
+ "target_handle_id": "e622fe61-3bca-4aff-86e1-25dad7bdf9d4",
205
+ "type": "DEFAULT",
206
+ },
207
+ {
208
+ "id": "e5598f3c-fb00-4f25-a0a6-9fb6af9d69a8",
209
+ "source_node_id": "dc8aecd0-49ba-4464-a45f-29d3bfd686e4",
210
+ "source_handle_id": "017d40f5-8326-4e42-a409-b08995defaa8",
211
+ "target_node_id": "127ef456-91bc-43c6-bd8b-1772db5e3cb5",
212
+ "target_handle_id": "e5cc41cb-71db-43ec-b3f0-c78706af3351",
213
+ "type": "DEFAULT",
214
+ },
215
+ {
216
+ "id": "8ff20817-974e-4a3a-bb65-f0ad73557649",
217
+ "source_node_id": "59243c65-053f-4ea6-9157-3f3edb1477bf",
218
+ "source_handle_id": "b9c5f52b-b714-46e8-a09c-38b4e770dd36",
219
+ "target_node_id": "37c10e8a-771b-432b-a767-31f5007851f0",
220
+ "target_handle_id": "0efd256f-f5f6-45fe-9adb-651780f5e63d",
221
+ "type": "DEFAULT",
222
+ },
223
+ {
224
+ "id": "0d8c801c-d76a-437a-831a-530885b75f96",
225
+ "source_node_id": "127ef456-91bc-43c6-bd8b-1772db5e3cb5",
226
+ "source_handle_id": "b0bd17f3-4ce6-4232-9666-ec8afa161bf2",
227
+ "target_node_id": "37c10e8a-771b-432b-a767-31f5007851f0",
228
+ "target_handle_id": "0efd256f-f5f6-45fe-9adb-651780f5e63d",
229
+ "type": "DEFAULT",
230
+ },
231
+ {
232
+ "id": "70c1005d-339a-41bc-b6c2-10bc30a0281c",
233
+ "source_node_id": "37c10e8a-771b-432b-a767-31f5007851f0",
234
+ "source_handle_id": "3bbc469f-0fb0-4b3d-a28b-746fefec2818",
235
+ "target_node_id": "634f0202-9ea9-4c62-b152-1a58c595cffb",
236
+ "target_handle_id": "acd48f48-54fb-4b2b-ab37-96d336f6dfb3",
237
+ "type": "DEFAULT",
238
+ },
239
+ {
240
+ "id": "3d031c93-09b1-4937-9f98-c30a7ba6823d",
241
+ "source_node_id": "634f0202-9ea9-4c62-b152-1a58c595cffb",
242
+ "source_handle_id": "de32167b-cf53-4df5-a344-1b9be852e9ff",
243
+ "target_node_id": "8187ce10-62b7-4a2c-8c0f-297387915467",
244
+ "target_handle_id": "ff55701c-16d3-4348-a633-6a298e71377d",
245
+ "type": "DEFAULT",
246
+ },
247
+ ],
248
+ serialized_edges,
249
+ ignore_order=True,
250
+ )
251
+
252
+ # AND the display data should be what we expect
253
+ display_data = workflow_raw_data["display_data"]
254
+ assert display_data == {
255
+ "viewport": {
256
+ "x": 0.0,
257
+ "y": 0.0,
258
+ "zoom": 1.0,
259
+ }
260
+ }
261
+
262
+ # AND the definition should be what we expect
263
+ definition = workflow_raw_data["definition"]
264
+ assert definition == {
265
+ "name": "AwaitAllPassingWorkflow",
266
+ "module": [
267
+ "tests",
268
+ "workflows",
269
+ "basic_merge_node",
270
+ "await_all_workflow",
271
+ ],
272
+ }