vellum-ai 1.11.2__py3-none-any.whl → 1.13.5__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.

Potentially problematic release.


This version of vellum-ai might be problematic. Click here for more details.

Files changed (275) hide show
  1. vellum/__init__.py +18 -0
  2. vellum/client/README.md +1 -1
  3. vellum/client/core/client_wrapper.py +2 -2
  4. vellum/client/core/force_multipart.py +4 -2
  5. vellum/client/core/http_response.py +1 -1
  6. vellum/client/core/pydantic_utilities.py +7 -4
  7. vellum/client/errors/too_many_requests_error.py +1 -2
  8. vellum/client/reference.md +677 -76
  9. vellum/client/resources/container_images/client.py +299 -0
  10. vellum/client/resources/container_images/raw_client.py +286 -0
  11. vellum/client/resources/documents/client.py +20 -10
  12. vellum/client/resources/documents/raw_client.py +20 -10
  13. vellum/client/resources/events/raw_client.py +4 -4
  14. vellum/client/resources/integration_auth_configs/client.py +2 -0
  15. vellum/client/resources/integration_auth_configs/raw_client.py +2 -0
  16. vellum/client/resources/integration_providers/client.py +28 -2
  17. vellum/client/resources/integration_providers/raw_client.py +24 -0
  18. vellum/client/resources/integrations/client.py +52 -4
  19. vellum/client/resources/integrations/raw_client.py +61 -0
  20. vellum/client/resources/workflow_deployments/client.py +156 -0
  21. vellum/client/resources/workflow_deployments/raw_client.py +334 -0
  22. vellum/client/resources/workflows/client.py +212 -8
  23. vellum/client/resources/workflows/raw_client.py +343 -6
  24. vellum/client/types/__init__.py +18 -0
  25. vellum/client/types/api_actor_type_enum.py +1 -1
  26. vellum/client/types/check_workflow_execution_status_error.py +21 -0
  27. vellum/client/types/check_workflow_execution_status_response.py +29 -0
  28. vellum/client/types/code_execution_package_request.py +21 -0
  29. vellum/client/types/composio_execute_tool_request.py +5 -0
  30. vellum/client/types/composio_tool_definition.py +1 -0
  31. vellum/client/types/container_image_build_config.py +1 -0
  32. vellum/client/types/container_image_container_image_tag.py +1 -0
  33. vellum/client/types/dataset_row_push_request.py +3 -0
  34. vellum/client/types/document_document_to_document_index.py +1 -0
  35. vellum/client/types/integration_name.py +24 -0
  36. vellum/client/types/node_execution_fulfilled_body.py +1 -0
  37. vellum/client/types/node_execution_log_body.py +24 -0
  38. vellum/client/types/node_execution_log_event.py +47 -0
  39. vellum/client/types/prompt_deployment_release_prompt_deployment.py +1 -0
  40. vellum/client/types/runner_config_request.py +24 -0
  41. vellum/client/types/severity_enum.py +5 -0
  42. vellum/client/types/slim_composio_tool_definition.py +1 -0
  43. vellum/client/types/slim_document_document_to_document_index.py +2 -0
  44. vellum/client/types/type_checker_enum.py +5 -0
  45. vellum/client/types/vellum_audio.py +5 -1
  46. vellum/client/types/vellum_audio_request.py +5 -1
  47. vellum/client/types/vellum_document.py +5 -1
  48. vellum/client/types/vellum_document_request.py +5 -1
  49. vellum/client/types/vellum_image.py +5 -1
  50. vellum/client/types/vellum_image_request.py +5 -1
  51. vellum/client/types/vellum_node_execution_event.py +2 -0
  52. vellum/client/types/vellum_variable.py +5 -0
  53. vellum/client/types/vellum_variable_extensions.py +1 -0
  54. vellum/client/types/vellum_variable_type.py +1 -0
  55. vellum/client/types/vellum_video.py +5 -1
  56. vellum/client/types/vellum_video_request.py +5 -1
  57. vellum/client/types/workflow_deployment_release_workflow_deployment.py +1 -0
  58. vellum/client/types/workflow_event.py +2 -0
  59. vellum/client/types/workflow_execution_fulfilled_body.py +1 -0
  60. vellum/client/types/workflow_result_event_output_data_array.py +1 -1
  61. vellum/client/types/workflow_result_event_output_data_chat_history.py +1 -1
  62. vellum/client/types/workflow_result_event_output_data_error.py +1 -1
  63. vellum/client/types/workflow_result_event_output_data_function_call.py +1 -1
  64. vellum/client/types/workflow_result_event_output_data_json.py +1 -1
  65. vellum/client/types/workflow_result_event_output_data_number.py +1 -1
  66. vellum/client/types/workflow_result_event_output_data_search_results.py +1 -1
  67. vellum/client/types/workflow_result_event_output_data_string.py +1 -1
  68. vellum/client/types/workflow_sandbox_execute_node_response.py +8 -0
  69. vellum/plugins/vellum_mypy.py +37 -2
  70. vellum/types/check_workflow_execution_status_error.py +3 -0
  71. vellum/types/check_workflow_execution_status_response.py +3 -0
  72. vellum/types/code_execution_package_request.py +3 -0
  73. vellum/types/node_execution_log_body.py +3 -0
  74. vellum/types/node_execution_log_event.py +3 -0
  75. vellum/types/runner_config_request.py +3 -0
  76. vellum/types/severity_enum.py +3 -0
  77. vellum/types/type_checker_enum.py +3 -0
  78. vellum/types/workflow_sandbox_execute_node_response.py +3 -0
  79. vellum/utils/files/mixin.py +26 -0
  80. vellum/utils/files/tests/test_mixin.py +62 -0
  81. vellum/utils/tests/test_vellum_client.py +95 -0
  82. vellum/utils/uuid.py +19 -2
  83. vellum/utils/vellum_client.py +10 -3
  84. vellum/workflows/__init__.py +7 -1
  85. vellum/workflows/descriptors/base.py +86 -0
  86. vellum/workflows/descriptors/tests/test_utils.py +9 -0
  87. vellum/workflows/errors/tests/__init__.py +0 -0
  88. vellum/workflows/errors/tests/test_types.py +52 -0
  89. vellum/workflows/errors/types.py +1 -0
  90. vellum/workflows/events/node.py +24 -0
  91. vellum/workflows/events/tests/test_event.py +123 -0
  92. vellum/workflows/events/types.py +2 -1
  93. vellum/workflows/events/workflow.py +28 -2
  94. vellum/workflows/expressions/add.py +3 -0
  95. vellum/workflows/expressions/tests/test_add.py +24 -0
  96. vellum/workflows/graph/graph.py +26 -5
  97. vellum/workflows/graph/tests/test_graph.py +228 -1
  98. vellum/workflows/inputs/base.py +22 -6
  99. vellum/workflows/inputs/dataset_row.py +121 -16
  100. vellum/workflows/inputs/tests/test_inputs.py +3 -3
  101. vellum/workflows/integrations/tests/test_vellum_integration_service.py +84 -0
  102. vellum/workflows/integrations/vellum_integration_service.py +12 -1
  103. vellum/workflows/loaders/base.py +2 -0
  104. vellum/workflows/nodes/bases/base.py +37 -16
  105. vellum/workflows/nodes/bases/tests/test_base_node.py +104 -1
  106. vellum/workflows/nodes/core/inline_subworkflow_node/node.py +1 -0
  107. vellum/workflows/nodes/core/inline_subworkflow_node/tests/test_node.py +1 -1
  108. vellum/workflows/nodes/core/map_node/node.py +7 -5
  109. vellum/workflows/nodes/core/map_node/tests/test_node.py +33 -0
  110. vellum/workflows/nodes/core/retry_node/node.py +1 -0
  111. vellum/workflows/nodes/core/try_node/node.py +1 -0
  112. vellum/workflows/nodes/displayable/api_node/node.py +3 -2
  113. vellum/workflows/nodes/displayable/api_node/tests/test_api_node.py +38 -0
  114. vellum/workflows/nodes/displayable/bases/api_node/node.py +1 -1
  115. vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py +18 -1
  116. vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py +109 -2
  117. vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +13 -2
  118. vellum/workflows/nodes/displayable/code_execution_node/node.py +9 -15
  119. vellum/workflows/nodes/displayable/code_execution_node/tests/test_node.py +65 -24
  120. vellum/workflows/nodes/displayable/code_execution_node/utils.py +3 -0
  121. vellum/workflows/nodes/displayable/final_output_node/node.py +24 -69
  122. vellum/workflows/nodes/displayable/final_output_node/tests/test_node.py +53 -3
  123. vellum/workflows/nodes/displayable/note_node/node.py +4 -1
  124. vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +16 -5
  125. vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py +47 -0
  126. vellum/workflows/nodes/displayable/tool_calling_node/node.py +74 -34
  127. vellum/workflows/nodes/displayable/tool_calling_node/tests/test_node.py +204 -8
  128. vellum/workflows/nodes/displayable/tool_calling_node/utils.py +92 -71
  129. vellum/workflows/nodes/mocks.py +47 -213
  130. vellum/workflows/nodes/tests/test_mocks.py +0 -177
  131. vellum/workflows/nodes/utils.py +23 -8
  132. vellum/workflows/outputs/base.py +36 -3
  133. vellum/workflows/references/environment_variable.py +1 -11
  134. vellum/workflows/references/lazy.py +8 -0
  135. vellum/workflows/references/state_value.py +24 -1
  136. vellum/workflows/references/tests/test_lazy.py +58 -0
  137. vellum/workflows/references/trigger.py +8 -3
  138. vellum/workflows/references/workflow_input.py +8 -0
  139. vellum/workflows/resolvers/resolver.py +13 -3
  140. vellum/workflows/resolvers/tests/test_resolver.py +31 -0
  141. vellum/workflows/runner/runner.py +159 -14
  142. vellum/workflows/runner/tests/__init__.py +0 -0
  143. vellum/workflows/runner/tests/test_runner.py +170 -0
  144. vellum/workflows/sandbox.py +7 -8
  145. vellum/workflows/state/base.py +89 -30
  146. vellum/workflows/state/context.py +74 -3
  147. vellum/workflows/state/tests/test_state.py +269 -1
  148. vellum/workflows/tests/test_dataset_row.py +8 -7
  149. vellum/workflows/tests/test_sandbox.py +97 -8
  150. vellum/workflows/triggers/__init__.py +2 -1
  151. vellum/workflows/triggers/base.py +160 -28
  152. vellum/workflows/triggers/chat_message.py +141 -0
  153. vellum/workflows/triggers/integration.py +12 -0
  154. vellum/workflows/triggers/manual.py +3 -1
  155. vellum/workflows/triggers/schedule.py +3 -1
  156. vellum/workflows/triggers/tests/test_chat_message.py +257 -0
  157. vellum/workflows/types/core.py +18 -0
  158. vellum/workflows/types/definition.py +6 -13
  159. vellum/workflows/types/generics.py +12 -0
  160. vellum/workflows/types/tests/test_utils.py +12 -0
  161. vellum/workflows/types/utils.py +32 -2
  162. vellum/workflows/types/workflow_metadata.py +124 -0
  163. vellum/workflows/utils/functions.py +152 -16
  164. vellum/workflows/utils/pydantic_schema.py +19 -1
  165. vellum/workflows/utils/tests/test_functions.py +123 -8
  166. vellum/workflows/utils/tests/test_validate.py +79 -0
  167. vellum/workflows/utils/tests/test_vellum_variables.py +62 -2
  168. vellum/workflows/utils/uuids.py +90 -0
  169. vellum/workflows/utils/validate.py +108 -0
  170. vellum/workflows/utils/vellum_variables.py +96 -16
  171. vellum/workflows/workflows/base.py +177 -35
  172. vellum/workflows/workflows/tests/test_base_workflow.py +51 -0
  173. {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/METADATA +6 -1
  174. {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/RECORD +274 -227
  175. vellum_cli/__init__.py +21 -0
  176. vellum_cli/config.py +16 -2
  177. vellum_cli/pull.py +2 -0
  178. vellum_cli/push.py +23 -10
  179. vellum_cli/tests/conftest.py +8 -13
  180. vellum_cli/tests/test_image_push.py +4 -11
  181. vellum_cli/tests/test_pull.py +83 -68
  182. vellum_cli/tests/test_push.py +251 -2
  183. vellum_ee/assets/node-definitions.json +225 -12
  184. vellum_ee/scripts/generate_node_definitions.py +15 -3
  185. vellum_ee/workflows/display/base.py +4 -3
  186. vellum_ee/workflows/display/nodes/base_node_display.py +44 -11
  187. vellum_ee/workflows/display/nodes/tests/test_base_node_display.py +93 -0
  188. vellum_ee/workflows/display/nodes/types.py +1 -0
  189. vellum_ee/workflows/display/nodes/vellum/__init__.py +0 -2
  190. vellum_ee/workflows/display/nodes/vellum/base_adornment_node.py +5 -2
  191. vellum_ee/workflows/display/nodes/vellum/code_execution_node.py +1 -1
  192. vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py +10 -2
  193. vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py +17 -14
  194. vellum_ee/workflows/display/nodes/vellum/map_node.py +2 -0
  195. vellum_ee/workflows/display/nodes/vellum/note_node.py +18 -3
  196. vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py +37 -14
  197. vellum_ee/workflows/display/nodes/vellum/tests/test_code_execution_node.py +62 -2
  198. vellum_ee/workflows/display/nodes/vellum/tests/test_final_output_node.py +136 -0
  199. vellum_ee/workflows/display/nodes/vellum/tests/test_note_node.py +44 -7
  200. vellum_ee/workflows/display/nodes/vellum/tests/test_prompt_node.py +5 -13
  201. vellum_ee/workflows/display/nodes/vellum/tests/test_subworkflow_deployment_node.py +27 -17
  202. vellum_ee/workflows/display/nodes/vellum/tests/test_tool_calling_node.py +145 -22
  203. vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py +107 -2
  204. vellum_ee/workflows/display/nodes/vellum/utils.py +54 -12
  205. vellum_ee/workflows/display/tests/test_base_workflow_display.py +13 -16
  206. vellum_ee/workflows/display/tests/test_json_schema_validation.py +190 -0
  207. vellum_ee/workflows/display/tests/test_mocks.py +912 -0
  208. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +14 -2
  209. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +109 -0
  210. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py +3 -0
  211. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py +187 -1
  212. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py +34 -325
  213. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +42 -393
  214. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +13 -315
  215. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_default_state_serialization.py +2 -122
  216. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py +24 -115
  217. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py +4 -93
  218. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py +7 -80
  219. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_prompt_node_serialization.py +9 -101
  220. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +77 -308
  221. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +62 -324
  222. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +3 -82
  223. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py +4 -142
  224. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_serialization.py +1 -61
  225. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_set_state_node_serialization.py +4 -4
  226. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py +205 -134
  227. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py +34 -146
  228. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py +2 -0
  229. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_composio_serialization.py +8 -6
  230. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_serialization.py +137 -266
  231. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_tool_wrapper_serialization.py +84 -0
  232. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_mcp_serialization.py +55 -16
  233. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_serialization.py +15 -1
  234. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_tool_wrapper_serialization.py +71 -0
  235. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_vellum_integration_serialization.py +119 -0
  236. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_workflow_deployment_serialization.py +1 -1
  237. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py +0 -2
  238. vellum_ee/workflows/display/tests/workflow_serialization/test_chat_message_dict_reference_serialization.py +22 -1
  239. vellum_ee/workflows/display/tests/workflow_serialization/test_chat_message_trigger_serialization.py +412 -0
  240. vellum_ee/workflows/display/tests/workflow_serialization/test_code_tool_node_reference_error.py +106 -0
  241. vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py +9 -41
  242. vellum_ee/workflows/display/tests/workflow_serialization/test_duplicate_trigger_name_validation.py +208 -0
  243. vellum_ee/workflows/display/tests/workflow_serialization/test_final_output_node_not_referenced_by_workflow_outputs.py +45 -0
  244. vellum_ee/workflows/display/tests/workflow_serialization/test_infinite_loop_validation.py +66 -0
  245. vellum_ee/workflows/display/tests/workflow_serialization/test_int_input_serialization.py +40 -0
  246. vellum_ee/workflows/display/tests/workflow_serialization/test_integration_trigger_serialization.py +8 -14
  247. vellum_ee/workflows/display/tests/workflow_serialization/test_integration_trigger_validation.py +173 -0
  248. vellum_ee/workflows/display/tests/workflow_serialization/test_integration_trigger_with_entrypoint_node_id.py +16 -13
  249. vellum_ee/workflows/display/tests/workflow_serialization/test_list_vellum_document_serialization.py +5 -1
  250. vellum_ee/workflows/display/tests/workflow_serialization/test_manual_trigger_serialization.py +12 -2
  251. vellum_ee/workflows/display/tests/workflow_serialization/test_multi_trigger_same_node_serialization.py +111 -0
  252. vellum_ee/workflows/display/tests/workflow_serialization/test_no_triggers_no_entrypoint_validation.py +64 -0
  253. vellum_ee/workflows/display/tests/workflow_serialization/test_partial_workflow_meta_display_override.py +55 -0
  254. vellum_ee/workflows/display/tests/workflow_serialization/test_sandbox_dataset_mocks_serialization.py +268 -0
  255. vellum_ee/workflows/display/tests/workflow_serialization/test_sandbox_invalid_pdf_data_url.py +49 -0
  256. vellum_ee/workflows/display/tests/workflow_serialization/test_sandbox_validation_errors.py +112 -0
  257. vellum_ee/workflows/display/tests/workflow_serialization/test_scheduled_trigger_serialization.py +25 -16
  258. vellum_ee/workflows/display/tests/workflow_serialization/test_terminal_node_in_unused_graphs_serialization.py +53 -0
  259. vellum_ee/workflows/display/utils/exceptions.py +34 -0
  260. vellum_ee/workflows/display/utils/expressions.py +463 -52
  261. vellum_ee/workflows/display/utils/metadata.py +98 -33
  262. vellum_ee/workflows/display/utils/tests/test_metadata.py +31 -0
  263. vellum_ee/workflows/display/utils/triggers.py +153 -0
  264. vellum_ee/workflows/display/utils/vellum.py +59 -5
  265. vellum_ee/workflows/display/workflows/base_workflow_display.py +656 -254
  266. vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py +26 -0
  267. vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +77 -29
  268. vellum_ee/workflows/server/namespaces.py +18 -0
  269. vellum_ee/workflows/tests/test_display_meta.py +2 -0
  270. vellum_ee/workflows/tests/test_serialize_module.py +174 -7
  271. vellum_ee/workflows/tests/test_server.py +0 -3
  272. vellum_ee/workflows/display/nodes/vellum/function_node.py +0 -14
  273. {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/LICENSE +0 -0
  274. {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/WHEEL +0 -0
  275. {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/entry_points.txt +0 -0
@@ -2,18 +2,21 @@ import pytest
2
2
  import io
3
3
  import json
4
4
  import os
5
+ import pathlib
5
6
  import tarfile
6
7
  from unittest import mock
7
8
  from uuid import uuid4
8
9
 
9
10
  from click.testing import CliRunner
10
11
  from httpx import Response
12
+ from pydantic import ValidationError
11
13
 
12
14
  from vellum.client.core.api_error import ApiError
13
15
  from vellum.client.types.workflow_push_response import WorkflowPushResponse
14
16
  from vellum.utils.uuid import is_valid_uuid
15
17
  from vellum_cli import main as cli_main
16
18
  from vellum_ee.workflows.display.nodes.utils import to_kebab_case
19
+ from vellum_ee.workflows.display.workflows.base_workflow_display import BaseWorkflowDisplay, WorkflowSerializationResult
17
20
 
18
21
 
19
22
  def _extract_tar_gz(tar_gz_bytes: bytes) -> dict[str, str]:
@@ -45,9 +48,15 @@ def _ensure_file(temp_dir: str, module: str, file_name: str, content: str) -> st
45
48
  def _ensure_workflow_py(temp_dir: str, module: str) -> str:
46
49
  workflow_py_file_content = """\
47
50
  from vellum.workflows import BaseWorkflow
51
+ from vellum.workflows.nodes.bases.base import BaseNode
48
52
 
49
- class ExampleWorkflow(BaseWorkflow):
53
+
54
+ class ExampleNode(BaseNode):
50
55
  pass
56
+
57
+
58
+ class ExampleWorkflow(BaseWorkflow):
59
+ graph = ExampleNode
51
60
  """
52
61
  return _ensure_file(temp_dir, module, "workflow.py", workflow_py_file_content)
53
62
 
@@ -173,6 +182,61 @@ def test_push__happy_path(mock_module, vellum_client, base_command):
173
182
  assert extracted_files["workflow.py"] == workflow_py_file_content
174
183
 
175
184
 
185
+ def test_push__forwards_dataset_to_client(mock_module, vellum_client, mocker):
186
+ """
187
+ Tests that the push command forwards the serialized dataset (scenarios)
188
+ to the API client when present.
189
+ """
190
+
191
+ # GIVEN a single workflow configured
192
+ temp_dir = mock_module.temp_dir
193
+ module = mock_module.module
194
+
195
+ # AND a workflow exists in the module successfully
196
+ _ensure_workflow_py(temp_dir, module)
197
+
198
+ # AND serialize_module returns an exec_config and a dataset with a workflow_trigger_id
199
+ fake_exec_config = {
200
+ "workflow_raw_data": {
201
+ "definition": {"name": "ExampleWorkflow"},
202
+ }
203
+ }
204
+ fake_dataset = [
205
+ {
206
+ "label": "Scenario 1",
207
+ "inputs": {},
208
+ "workflow_trigger_id": "trigger-123",
209
+ }
210
+ ]
211
+ mocker.patch.object(
212
+ BaseWorkflowDisplay,
213
+ "serialize_module",
214
+ return_value=WorkflowSerializationResult(
215
+ exec_config=fake_exec_config,
216
+ errors=[],
217
+ dataset=fake_dataset,
218
+ ),
219
+ )
220
+
221
+ # AND the push API call returns successfully
222
+ vellum_client.workflows.push.return_value = WorkflowPushResponse(
223
+ workflow_sandbox_id=str(uuid4()),
224
+ )
225
+
226
+ # WHEN calling `vellum workflows push`
227
+ runner = CliRunner()
228
+ result = runner.invoke(cli_main, ["workflows", "push", module])
229
+
230
+ # THEN it should succeed
231
+ assert result.exit_code == 0
232
+
233
+ # AND we should have called the push API with the dataset argument
234
+ vellum_client.workflows.push.assert_called_once()
235
+ call_args = vellum_client.workflows.push.call_args.kwargs
236
+ assert "dataset" in call_args
237
+ assert json.loads(call_args["dataset"]) == fake_dataset
238
+
239
+
176
240
  @pytest.mark.usefixtures("info_log_level")
177
241
  def test_push__verify_default_url_in_raw_httpx_transport(mock_module, mock_httpx_transport):
178
242
  # GIVEN a single workflow configured
@@ -659,7 +723,9 @@ def test_push__push_fails_due_to_404_error_with_id(mock_module, vellum_client):
659
723
  assert "Traceback" not in result.output
660
724
 
661
725
 
662
- def test_push__push_fails_due_to_404_error_without_id(tmp_path, vellum_client, monkeypatch):
726
+ def test_push__push_fails_due_to_404_error_without_id(
727
+ tmp_path: pathlib.Path, vellum_client, monkeypatch: pytest.MonkeyPatch
728
+ ):
663
729
  """
664
730
  Tests that a 404 error without a workflow sandbox ID shows a helpful error message.
665
731
  """
@@ -680,6 +746,7 @@ def test_push__push_fails_due_to_404_error_without_id(tmp_path, vellum_client, m
680
746
  pyproject_file.write_text(f'[tool.vellum]\n[[tool.vellum.workflows]]\nmodule = "{module}"\n')
681
747
 
682
748
  monkeypatch.chdir(tmp_path)
749
+ monkeypatch.setenv("VELLUM_API_KEY", "abcdef123456")
683
750
 
684
751
  # AND the push API call returns a 404 response
685
752
  vellum_client.workflows.push.side_effect = ApiError(
@@ -1375,3 +1442,185 @@ def test_push__workspace_option__nonexistent_workspace_should_fail(mock_module):
1375
1442
  assert "Available workspaces:" in result.output
1376
1443
  assert "default" in result.output
1377
1444
  assert "my_custom_workspace" in result.output
1445
+
1446
+
1447
+ def test_push__validation_error_during_serialization(mock_module, mocker):
1448
+ """
1449
+ Tests that a ValidationError raised during workflow serialization is handled gracefully
1450
+ with a user-friendly error message.
1451
+ """
1452
+ # GIVEN a single workflow configured
1453
+ temp_dir = mock_module.temp_dir
1454
+ module = mock_module.module
1455
+
1456
+ # AND a workflow exists in the module successfully
1457
+ _ensure_workflow_py(temp_dir, module)
1458
+
1459
+ # AND BaseWorkflowDisplay.serialize_module raises a ValidationError
1460
+ mock_serialize_module = mocker.patch(
1461
+ "vellum_ee.workflows.display.workflows.base_workflow_display.BaseWorkflowDisplay.serialize_module",
1462
+ side_effect=ValidationError.from_exception_data(
1463
+ "WorkflowConfig",
1464
+ [
1465
+ {
1466
+ "type": "missing",
1467
+ "loc": ("field",),
1468
+ "msg": "Field required", # type: ignore[typeddict-item]
1469
+ "input": {"invalid": "data"},
1470
+ }
1471
+ ],
1472
+ ),
1473
+ )
1474
+
1475
+ # WHEN calling `vellum push`
1476
+ runner = CliRunner()
1477
+ result = runner.invoke(cli_main, ["push", module])
1478
+
1479
+ # THEN it should exit with an error
1480
+ assert result.exit_code == 1
1481
+
1482
+ # AND serialize_module should have been called
1483
+ mock_serialize_module.assert_called_once()
1484
+
1485
+ # AND the error message should contain the validation error title
1486
+ assert f"Validation error while trying to push {module}" in result.output
1487
+
1488
+ # AND the error message should contain the validation error details
1489
+ assert "Field required" in result.output
1490
+
1491
+
1492
+ def test_push__includes_metadata_json_in_artifact(mock_module, vellum_client):
1493
+ """
1494
+ Tests that the push command includes metadata.json in the artifact.
1495
+ """
1496
+
1497
+ # GIVEN a single workflow configured
1498
+ temp_dir = mock_module.temp_dir
1499
+ module = mock_module.module
1500
+
1501
+ # AND a workflow exists in the module successfully
1502
+ workflow_py_file_content = _ensure_workflow_py(temp_dir, module)
1503
+
1504
+ # AND a metadata.json file exists in the module
1505
+ metadata_json_content = _ensure_file(temp_dir, module, "metadata.json", '{"key": "value"}')
1506
+
1507
+ # AND the push API call returns successfully
1508
+ vellum_client.workflows.push.return_value = WorkflowPushResponse(
1509
+ workflow_sandbox_id=str(uuid4()),
1510
+ )
1511
+
1512
+ # WHEN calling `vellum workflows push`
1513
+ runner = CliRunner()
1514
+ result = runner.invoke(cli_main, ["workflows", "push", module])
1515
+
1516
+ # THEN it should succeed
1517
+ assert result.exit_code == 0
1518
+
1519
+ # AND we should have called the push API with the correct args
1520
+ vellum_client.workflows.push.assert_called_once()
1521
+ call_args = vellum_client.workflows.push.call_args.kwargs
1522
+
1523
+ # AND the artifact should contain both workflow.py and metadata.json
1524
+ extracted_files = _extract_tar_gz(call_args["artifact"].read())
1525
+ assert extracted_files["workflow.py"] == workflow_py_file_content
1526
+ assert extracted_files["metadata.json"] == metadata_json_content
1527
+
1528
+ # AND metadata.json should NOT be in the exec_config's module_data additional_files
1529
+ exec_config = json.loads(call_args["exec_config"])
1530
+ module_data = exec_config.get("module_data") or {}
1531
+ additional_files = module_data.get("additional_files") or {}
1532
+ assert "metadata.json" not in additional_files
1533
+
1534
+
1535
+ def test_push__workspace_option__same_module_different_workspaces_in_lockfile_uses_correct_sandbox_id(
1536
+ mock_module, vellum_client_class
1537
+ ):
1538
+ """
1539
+ Tests that when pushing with --workspace flag, the correct workflow_sandbox_id
1540
+ is used based on the workspace when configs are in the lockfile.
1541
+ """
1542
+
1543
+ # GIVEN a module configured for two different workspaces with the same sandbox ID in the lockfile
1544
+ temp_dir = mock_module.temp_dir
1545
+ module = mock_module.module
1546
+ workflow_sandbox_id = str(uuid4())
1547
+
1548
+ # AND the lockfile has the same module and sandbox ID configured for two workspaces
1549
+ with open(os.path.join(temp_dir, "vellum.lock.json"), "w") as f:
1550
+ json.dump(
1551
+ {
1552
+ "version": "1.0",
1553
+ "workflows": [
1554
+ {
1555
+ "module": module,
1556
+ "workflow_sandbox_id": workflow_sandbox_id,
1557
+ "workspace": "default",
1558
+ "container_image_name": None,
1559
+ "container_image_tag": None,
1560
+ "deployments": [],
1561
+ "ignore": None,
1562
+ "target_directory": None,
1563
+ },
1564
+ {
1565
+ "module": module,
1566
+ "workflow_sandbox_id": workflow_sandbox_id,
1567
+ "workspace": "other",
1568
+ "container_image_name": None,
1569
+ "container_image_tag": None,
1570
+ "deployments": [],
1571
+ "ignore": None,
1572
+ "target_directory": None,
1573
+ },
1574
+ ],
1575
+ "workspaces": [],
1576
+ },
1577
+ f,
1578
+ indent=2,
1579
+ )
1580
+
1581
+ # AND the pyproject.toml has the first workflow config and workspace config
1582
+ mock_module.set_pyproject_toml(
1583
+ {
1584
+ "workflows": [
1585
+ {
1586
+ "module": module,
1587
+ "workflow_sandbox_id": workflow_sandbox_id,
1588
+ }
1589
+ ],
1590
+ "workspaces": [
1591
+ {
1592
+ "name": "other",
1593
+ "api_key": "OTHER_VELLUM_API_KEY",
1594
+ }
1595
+ ],
1596
+ }
1597
+ )
1598
+
1599
+ # AND the .env file has both api keys stored
1600
+ with open(os.path.join(temp_dir, ".env"), "w") as f:
1601
+ f.write(
1602
+ """\
1603
+ VELLUM_API_KEY=default_api_key_123
1604
+ OTHER_VELLUM_API_KEY=other_api_key_456
1605
+ """
1606
+ )
1607
+
1608
+ # AND a workflow exists in the module
1609
+ _ensure_workflow_py(temp_dir, module)
1610
+
1611
+ # AND the push API call returns successfully
1612
+ vellum_client_class.return_value.workflows.push.return_value = WorkflowPushResponse(
1613
+ workflow_sandbox_id=workflow_sandbox_id,
1614
+ )
1615
+
1616
+ # WHEN calling `vellum push` with --workspace other
1617
+ runner = CliRunner()
1618
+ result = runner.invoke(cli_main, ["push", module, "--workspace", "other"])
1619
+
1620
+ # THEN it should succeed
1621
+ assert result.exit_code == 0, result.output
1622
+
1623
+ # AND we should have called the push API with the correct workflow_sandbox_id
1624
+ vellum_client_class.return_value.workflows.push.assert_called_once()
1625
+ call_args = vellum_client_class.return_value.workflows.push.call_args.kwargs
1626
+ assert call_args["workflow_sandbox_id"] == workflow_sandbox_id
@@ -53,25 +53,40 @@
53
53
  "id": "fd55dc40-4e55-4327-8a89-d4123bb775df",
54
54
  "name": "json",
55
55
  "type": "JSON",
56
- "value": null
56
+ "value": null,
57
+ "schema": {
58
+ "$ref": "#/$defs/vellum.workflows.types.core.Json"
59
+ }
57
60
  },
58
61
  {
59
62
  "id": "357a9805-da18-400c-9ce5-152be1dd2ff8",
60
63
  "name": "headers",
61
64
  "type": "JSON",
62
- "value": null
65
+ "value": null,
66
+ "schema": {
67
+ "type": "object",
68
+ "additionalProperties": {
69
+ "type": "string"
70
+ }
71
+ }
63
72
  },
64
73
  {
65
74
  "id": "4e8c472c-5f32-4d41-9746-4085b3e8b6ef",
66
75
  "name": "status_code",
67
76
  "type": "NUMBER",
68
- "value": null
77
+ "value": null,
78
+ "schema": {
79
+ "type": "integer"
80
+ }
69
81
  },
70
82
  {
71
83
  "id": "90d2ccc0-40da-40c5-895d-adf7d2de28d3",
72
84
  "name": "text",
73
85
  "type": "STRING",
74
- "value": null
86
+ "value": null,
87
+ "schema": {
88
+ "type": "string"
89
+ }
75
90
  }
76
91
  ],
77
92
  "attributes": [
@@ -133,6 +148,26 @@
133
148
  "name": "default",
134
149
  "type": "DEFAULT"
135
150
  }
151
+ ],
152
+ "outputs": [
153
+ {
154
+ "id": "cd6cf124-b178-4852-b5d5-251f5835fc8f",
155
+ "name": "result",
156
+ "type": "STRING",
157
+ "value": null,
158
+ "schema": {
159
+ "type": "string"
160
+ }
161
+ },
162
+ {
163
+ "id": "c86c2620-9192-412c-9423-4f594411fd47",
164
+ "name": "log",
165
+ "type": "STRING",
166
+ "value": null,
167
+ "schema": {
168
+ "type": "string"
169
+ }
170
+ }
136
171
  ]
137
172
  },
138
173
  {
@@ -435,6 +470,13 @@
435
470
  },
436
471
  {
437
472
  "id": "62ba7250-8508-41f1-8f14-709902c0e734",
473
+ "attributes": [
474
+ {
475
+ "id": "eb7d528f-3dae-4eac-91ff-957766be58c7",
476
+ "name": "items",
477
+ "value": null
478
+ }
479
+ ],
438
480
  "display_data": {
439
481
  "position": {
440
482
  "x": 0.0,
@@ -617,7 +659,8 @@
617
659
  "name": "default",
618
660
  "type": "DEFAULT"
619
661
  }
620
- ]
662
+ ],
663
+ "outputs": []
621
664
  },
622
665
  {
623
666
  "id": "e1c8d236-6131-4218-aed8-45f986723227",
@@ -798,7 +841,11 @@
798
841
  "id": "57687d69-eb14-48fe-b919-abb044c85c35",
799
842
  "name": "results",
800
843
  "type": "JSON",
801
- "value": null
844
+ "value": null,
845
+ "schema": {
846
+ "type": "object",
847
+ "additionalProperties": {}
848
+ }
802
849
  }
803
850
  ]
804
851
  },
@@ -986,17 +1033,36 @@
986
1033
  }
987
1034
  ],
988
1035
  "outputs": [
1036
+ {
1037
+ "id": "1e346d06-a0d9-45d4-8d74-7df1f2c6d1dc",
1038
+ "name": "json",
1039
+ "type": "JSON",
1040
+ "value": null,
1041
+ "schema": {
1042
+ "type": "object",
1043
+ "additionalProperties": {}
1044
+ }
1045
+ },
989
1046
  {
990
1047
  "id": "bd83c7f1-fc8d-4441-abcf-95641aa03fcb",
991
1048
  "name": "text",
992
1049
  "type": "STRING",
993
- "value": null
1050
+ "value": null,
1051
+ "schema": {
1052
+ "type": "string"
1053
+ }
994
1054
  },
995
1055
  {
996
1056
  "id": "bb08b1a9-9745-475a-b030-6bb5b2146984",
997
1057
  "name": "chat_history",
998
1058
  "type": "CHAT_HISTORY",
999
- "value": null
1059
+ "value": null,
1060
+ "schema": {
1061
+ "type": "array",
1062
+ "items": {
1063
+ "$ref": "#/$defs/vellum.client.types.chat_message.ChatMessage"
1064
+ }
1065
+ }
1000
1066
  }
1001
1067
  ]
1002
1068
  },
@@ -1065,19 +1131,35 @@
1065
1131
  "id": "71bb6f36-d0cc-4c01-8dc2-1a0b98429c81",
1066
1132
  "name": "text",
1067
1133
  "type": "STRING",
1068
- "value": null
1134
+ "value": null,
1135
+ "schema": {
1136
+ "type": "string"
1137
+ }
1069
1138
  },
1070
1139
  {
1071
1140
  "id": "9df3ddf0-675f-48d5-b4b2-e3a805bbf450",
1072
1141
  "name": "urls",
1073
1142
  "type": "JSON",
1074
- "value": null
1143
+ "value": null,
1144
+ "schema": {
1145
+ "type": "array",
1146
+ "items": {
1147
+ "type": "string"
1148
+ }
1149
+ }
1075
1150
  },
1076
1151
  {
1077
1152
  "id": "87994bf1-d8d7-40d0-a715-90b1e399c5f2",
1078
1153
  "name": "results",
1079
1154
  "type": "JSON",
1080
- "value": null
1155
+ "value": null,
1156
+ "schema": {
1157
+ "type": "array",
1158
+ "items": {
1159
+ "type": "object",
1160
+ "additionalProperties": {}
1161
+ }
1162
+ }
1081
1163
  }
1082
1164
  ]
1083
1165
  },
@@ -1126,10 +1208,141 @@
1126
1208
  "id": "c65369bf-7dbc-4f66-87c5-381c965ffb5d",
1127
1209
  "name": "value",
1128
1210
  "type": "STRING",
1129
- "value": null
1211
+ "value": null,
1212
+ "schema": {
1213
+ "type": "string"
1214
+ }
1130
1215
  }
1131
1216
  ]
1132
1217
  }
1133
1218
  ],
1219
+ "triggers": [
1220
+ {
1221
+ "type": "CHAT_MESSAGE",
1222
+ "name": "ChatMessageTrigger",
1223
+ "module": [
1224
+ "vellum",
1225
+ "workflows",
1226
+ "triggers",
1227
+ "chat_message"
1228
+ ],
1229
+ "attributes": [
1230
+ {
1231
+ "id": "88a07223-94d0-411c-acb4-37a2b2ab108d",
1232
+ "key": "message",
1233
+ "type": "ARRAY",
1234
+ "required": true,
1235
+ "default": {
1236
+ "type": "ARRAY",
1237
+ "value": null
1238
+ },
1239
+ "extensions": null,
1240
+ "schema": {
1241
+ "anyOf": [
1242
+ {
1243
+ "type": "string"
1244
+ },
1245
+ {
1246
+ "type": "array",
1247
+ "items": {
1248
+ "$ref": "#/$defs/vellum.client.types.array_chat_message_content_item.ArrayChatMessageContentItem"
1249
+ }
1250
+ }
1251
+ ]
1252
+ }
1253
+ }
1254
+ ],
1255
+ "display_data": {
1256
+ "label": "Chat Message",
1257
+ "position": {
1258
+ "x": 0.0,
1259
+ "y": 0.0
1260
+ },
1261
+ "z_index": 0,
1262
+ "icon": "vellum:icon:message-dots",
1263
+ "color": "blue"
1264
+ }
1265
+ },
1266
+ {
1267
+ "type": "INTEGRATION",
1268
+ "name": "IntegrationTrigger",
1269
+ "module": [
1270
+ "vellum",
1271
+ "workflows",
1272
+ "triggers",
1273
+ "integration"
1274
+ ],
1275
+ "attributes": [],
1276
+ "display_data": {
1277
+ "label": "Trigger",
1278
+ "position": {
1279
+ "x": 0.0,
1280
+ "y": 0.0
1281
+ },
1282
+ "z_index": 0
1283
+ }
1284
+ },
1285
+ {
1286
+ "type": "MANUAL",
1287
+ "name": "ManualTrigger",
1288
+ "module": [
1289
+ "vellum",
1290
+ "workflows",
1291
+ "triggers",
1292
+ "manual"
1293
+ ],
1294
+ "attributes": []
1295
+ },
1296
+ {
1297
+ "type": "SCHEDULED",
1298
+ "name": "ScheduleTrigger",
1299
+ "module": [
1300
+ "vellum",
1301
+ "workflows",
1302
+ "triggers",
1303
+ "schedule"
1304
+ ],
1305
+ "attributes": [
1306
+ {
1307
+ "id": "77f5f59d-d9b8-4a9c-b223-e3f5d9f4e376",
1308
+ "key": "current_run_at",
1309
+ "type": "STRING",
1310
+ "required": true,
1311
+ "default": {
1312
+ "type": "STRING",
1313
+ "value": null
1314
+ },
1315
+ "extensions": null,
1316
+ "schema": {
1317
+ "type": "string",
1318
+ "format": "date-time"
1319
+ }
1320
+ },
1321
+ {
1322
+ "id": "e75ec8ba-2635-4be2-9c1d-f04ddcb8a7a1",
1323
+ "key": "next_run_at",
1324
+ "type": "STRING",
1325
+ "required": true,
1326
+ "default": {
1327
+ "type": "STRING",
1328
+ "value": null
1329
+ },
1330
+ "extensions": null,
1331
+ "schema": {
1332
+ "type": "string",
1333
+ "format": "date-time"
1334
+ }
1335
+ }
1336
+ ],
1337
+ "display_data": {
1338
+ "label": "Trigger",
1339
+ "position": {
1340
+ "x": 0.0,
1341
+ "y": 0.0
1342
+ },
1343
+ "z_index": 0
1344
+ }
1345
+ }
1346
+ ],
1134
1347
  "errors": []
1135
1348
  }
@@ -8,6 +8,7 @@ import vellum.workflows.nodes.displayable as displayable_module
8
8
  from vellum.workflows.vellum_client import create_vellum_client
9
9
  from vellum_ee.workflows.display.nodes.get_node_display_class import get_node_display_class
10
10
  from vellum_ee.workflows.display.types import WorkflowDisplayContext
11
+ from vellum_ee.workflows.display.utils.triggers import get_all_trigger_classes, serialize_trigger_definition
11
12
 
12
13
  logger = logging.getLogger(__name__)
13
14
 
@@ -49,7 +50,7 @@ def serialize_node_definition(
49
50
 
50
51
 
51
52
  def main() -> None:
52
- """Main function to generate node definitions."""
53
+ """Main function to generate node and trigger definitions."""
53
54
  logger.info("Generating node definitions...")
54
55
 
55
56
  display_context = create_display_context_with_client()
@@ -72,7 +73,17 @@ def main() -> None:
72
73
  except Exception as e:
73
74
  errors.append({"node": node_class.__name__, "error": f"{e.__class__.__name__}: {str(e)}"})
74
75
 
75
- result = {"nodes": successful_nodes, "errors": errors}
76
+ # Generate trigger definitions
77
+ logger.info("Generating trigger definitions...")
78
+ trigger_classes = get_all_trigger_classes()
79
+ triggers = []
80
+
81
+ for trigger_class in trigger_classes:
82
+ logger.info(f"Serializing {trigger_class.__name__}...")
83
+ trigger_definition = serialize_trigger_definition(trigger_class)
84
+ triggers.append(trigger_definition)
85
+
86
+ result = {"nodes": successful_nodes, "triggers": triggers, "errors": errors}
76
87
 
77
88
  output_path = "ee/vellum_ee/assets/node-definitions.json"
78
89
  os.makedirs(os.path.dirname(output_path), exist_ok=True)
@@ -81,7 +92,8 @@ def main() -> None:
81
92
  json.dump(result, f, indent=2)
82
93
 
83
94
  logger.info(
84
- f"Generated {len(successful_nodes)} successful node definitions and {len(errors)} errors in {output_path}"
95
+ f"Generated {len(successful_nodes)} node definitions, {len(triggers)} trigger definitions, "
96
+ f"and {len(errors)} errors in {output_path}"
85
97
  )
86
98
 
87
99
 
@@ -18,6 +18,7 @@ class WorkflowTriggerType(Enum):
18
18
  MANUAL = "MANUAL"
19
19
  INTEGRATION = "INTEGRATION"
20
20
  SCHEDULED = "SCHEDULED"
21
+ CHAT_MESSAGE = "CHAT_MESSAGE"
21
22
 
22
23
 
23
24
  def get_trigger_type_mapping() -> Dict[Type["BaseTrigger"], WorkflowTriggerType]:
@@ -49,9 +50,9 @@ class WorkflowDisplayData(UniversalBaseModel):
49
50
 
50
51
  @dataclass
51
52
  class WorkflowMetaDisplay:
52
- entrypoint_node_id: UUID
53
- entrypoint_node_source_handle_id: UUID
54
- entrypoint_node_display: NodeDisplayData = Field(default_factory=NodeDisplayData)
53
+ entrypoint_node_id: Optional[UUID] = None
54
+ entrypoint_node_source_handle_id: Optional[UUID] = None
55
+ entrypoint_node_display: Optional[NodeDisplayData] = None
55
56
  display_data: WorkflowDisplayData = field(default_factory=WorkflowDisplayData)
56
57
 
57
58
  @classmethod