vellum-ai 0.12.15__py3-none-any.whl → 0.12.17__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 (48) hide show
  1. vellum/client/core/client_wrapper.py +1 -1
  2. vellum/plugins/vellum_mypy.py +80 -11
  3. vellum/prompts/blocks/compilation.py +43 -0
  4. vellum/utils/templating/render.py +3 -0
  5. vellum/workflows/nodes/bases/base.py +4 -0
  6. vellum/workflows/nodes/core/inline_subworkflow_node/node.py +10 -2
  7. vellum/workflows/nodes/core/inline_subworkflow_node/tests/test_node.py +16 -0
  8. vellum/workflows/nodes/core/retry_node/node.py +24 -3
  9. vellum/workflows/nodes/core/retry_node/tests/test_node.py +40 -0
  10. vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py +20 -1
  11. vellum/workflows/nodes/displayable/api_node/node.py +3 -3
  12. {vellum_ai-0.12.15.dist-info → vellum_ai-0.12.17.dist-info}/METADATA +10 -8
  13. {vellum_ai-0.12.15.dist-info → vellum_ai-0.12.17.dist-info}/RECORD +48 -45
  14. vellum_cli/__init__.py +14 -0
  15. vellum_cli/pull.py +7 -4
  16. vellum_cli/push.py +26 -4
  17. vellum_cli/tests/conftest.py +4 -2
  18. vellum_cli/tests/test_push.py +75 -4
  19. vellum_ee/workflows/display/nodes/vellum/api_node.py +3 -3
  20. vellum_ee/workflows/display/nodes/vellum/base_node.py +17 -0
  21. vellum_ee/workflows/display/nodes/vellum/code_execution_node.py +2 -2
  22. vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py +2 -2
  23. vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py +20 -6
  24. vellum_ee/workflows/display/nodes/vellum/map_node.py +1 -0
  25. vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py +2 -2
  26. vellum_ee/workflows/display/nodes/vellum/search_node.py +4 -2
  27. vellum_ee/workflows/display/nodes/vellum/templating_node.py +1 -1
  28. vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py +3 -3
  29. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/__init__.py +0 -0
  30. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py +28 -0
  31. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py +123 -0
  32. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +2 -11
  33. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py +2 -14
  34. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py +1 -7
  35. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +17 -1
  36. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +17 -1
  37. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +1 -9
  38. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py +1 -1
  39. vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py +1 -4
  40. vellum_ee/workflows/display/types.py +5 -1
  41. vellum_ee/workflows/display/utils/vellum.py +3 -3
  42. vellum_ee/workflows/display/vellum.py +4 -0
  43. vellum_ee/workflows/display/workflows/base_workflow_display.py +44 -16
  44. vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py +3 -0
  45. vellum_ee/workflows/display/workflows/vellum_workflow_display.py +7 -8
  46. {vellum_ai-0.12.15.dist-info → vellum_ai-0.12.17.dist-info}/LICENSE +0 -0
  47. {vellum_ai-0.12.15.dist-info → vellum_ai-0.12.17.dist-info}/WHEEL +0 -0
  48. {vellum_ai-0.12.15.dist-info → vellum_ai-0.12.17.dist-info}/entry_points.txt +0 -0
@@ -1,18 +1,18 @@
1
1
  vellum_cli/CONTRIBUTING.md,sha256=FtDC7BGxSeMnwCXAUssFsAIElXtmJE-O5Z7BpolcgvI,2935
2
2
  vellum_cli/README.md,sha256=2NudRoLzWxNKqnuVy1JuQ7DerIaxWGYkrH8kMd-asIE,90
3
- vellum_cli/__init__.py,sha256=iims87aL6HbwggCAh8JfLBNf3C7tN3TGDmlg7V5W9Lg,8506
3
+ vellum_cli/__init__.py,sha256=7liY2AX5t51Vd_usohIU6QSLjAsF6MaHD30L6ng9SSg,8926
4
4
  vellum_cli/aliased_group.py,sha256=ugW498j0yv4ALJ8vS9MsO7ctDW7Jlir9j6nE_uHAP8c,3363
5
5
  vellum_cli/config.py,sha256=998IZbvkrw2avjbvs8bw6NrbEgGz5UBKRbvKAcastJg,5493
6
6
  vellum_cli/image_push.py,sha256=SJwhwWJsLjwGNezNVd_oCVpFMfPsAB3dfLWmriZZUtw,4419
7
7
  vellum_cli/logger.py,sha256=PuRFa0WCh4sAGFS5aqWB0QIYpS6nBWwPJrIXpWxugV4,1022
8
- vellum_cli/pull.py,sha256=hYQBe2_-Y4Ieh_Jo54EwBUpqPYq6UYitUBPgqyOVba0,7499
9
- vellum_cli/push.py,sha256=00VHNlUc41UdO59gwIhSuk3AFL3kDITNQdWCdnYAtxc,5633
8
+ vellum_cli/pull.py,sha256=zf0y22XptUYI_hMP_4Q1CEo9s2wALsTJcCXNd-_ibd8,7551
9
+ vellum_cli/push.py,sha256=iQ2H-vY8njqiYgIifGooqopqkb1BUUA3I7IN7VIHKv8,6149
10
10
  vellum_cli/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
- vellum_cli/tests/conftest.py,sha256=eFGwBxib3Nki830lIFintB0b6r4x8T_KMnmzhlTY5x0,1337
11
+ vellum_cli/tests/conftest.py,sha256=Jv-QUjXoCDhsvVvXEjOenNqRArO_xXhtNuCYt4wiOyE,1421
12
12
  vellum_cli/tests/test_config.py,sha256=uvKGDc8BoVyT9_H0Z-g8469zVxomn6Oi3Zj-vK7O_wU,2631
13
13
  vellum_cli/tests/test_main.py,sha256=qDZG-aQauPwBwM6A2DIu1494n47v3pL28XakTbLGZ-k,272
14
14
  vellum_cli/tests/test_pull.py,sha256=6gbASF6ASy5YcdWjOCt6b5K0u2VWsFegdrTWu6sEVKs,19613
15
- vellum_cli/tests/test_push.py,sha256=NpwGXuZSzrR7B6hBO1UF9O8im13_LlpSqncVSdzYDiQ,5812
15
+ vellum_cli/tests/test_push.py,sha256=8o8DFW9HCakhfZMS1Iql13RC90hF9pM630Y-rQbo234,8593
16
16
  vellum_ee/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
17
  vellum_ee/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
18
  vellum_ee/workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -27,53 +27,56 @@ vellum_ee/workflows/display/nodes/tests/test_base_node_display.py,sha256=QqR3Ly0
27
27
  vellum_ee/workflows/display/nodes/types.py,sha256=St1BB6no528OyELGiyRabWao0GGw6mLhstQAvEACbGk,247
28
28
  vellum_ee/workflows/display/nodes/utils.py,sha256=sloya5TpXsnot1HURc9L51INwflRqUzHxRVnCS9Cd-4,973
29
29
  vellum_ee/workflows/display/nodes/vellum/__init__.py,sha256=_raKY9eKi_OvIFn6nGvf9xKSboKtYLHCWaWCwDQFbOc,1567
30
- vellum_ee/workflows/display/nodes/vellum/api_node.py,sha256=4SSQGecKWHuoGy5YIGJeOZVHGKwTs_8Y-gf3GvsHb0M,8506
31
- vellum_ee/workflows/display/nodes/vellum/base_node.py,sha256=CBE-4tgQhk5zEcQqGQ0R6ZqZbtNuxAaJ5tDD8jDLOfY,672
32
- vellum_ee/workflows/display/nodes/vellum/code_execution_node.py,sha256=qrf2Ne8n2aaoa2xgK3ExCEGI9BA-2g1zmvjSHyzCWmQ,4230
30
+ vellum_ee/workflows/display/nodes/vellum/api_node.py,sha256=zucBb2neqTig5Q3HCiMrksRdg-WISnR2prFxYzk3WL0,8527
31
+ vellum_ee/workflows/display/nodes/vellum/base_node.py,sha256=M59-Kwz6bQ_j8yWLAtJikye-iOl5WtMI8eMnTtvb8SQ,1508
32
+ vellum_ee/workflows/display/nodes/vellum/code_execution_node.py,sha256=Kp-0YRZoy_Pi7HdwUgBxV57a6BzyoxotsvFsfoSGg40,4244
33
33
  vellum_ee/workflows/display/nodes/vellum/conditional_node.py,sha256=EtdqJfhYw03PuT2iyJ6mSAZK4RsQqDie_2AnJAtMelk,13625
34
34
  vellum_ee/workflows/display/nodes/vellum/error_node.py,sha256=ygTjSjYDI4DtkxADWub5rhBnRWItMKWF6fezBrgpOKA,1979
35
35
  vellum_ee/workflows/display/nodes/vellum/final_output_node.py,sha256=t5iJQVoRT5g-v2IiUb4kFYdvUVKch0zn27016pzDZoo,2761
36
36
  vellum_ee/workflows/display/nodes/vellum/guardrail_node.py,sha256=3TJvHX_Uuf_gr94VkYc_zmNH8I5p71ChIeoAbJZ3ddY,2158
37
- vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py,sha256=DYhxHgFT06CNCpovO4Z-wFPqCjFKxyl89ygFs8AucRQ,7189
38
- vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py,sha256=IqPQdlxLdaMirgDbOSxq17d8bolqqjjRPy4t3YCBhmc,5028
39
- vellum_ee/workflows/display/nodes/vellum/map_node.py,sha256=AqUlItgSZij12qRKguKVmDbbaLuDy3Cdom5uOlJPqrc,3640
37
+ vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py,sha256=dcrCIIWeL5RDHEmc9eyHEdDvxrzQddm71TUtLVcVH8I,7203
38
+ vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py,sha256=_cdCzwbwB3gvcLz3UOgvmpz_AZwhXaU8CsOj9nuHB0M,5566
39
+ vellum_ee/workflows/display/nodes/vellum/map_node.py,sha256=y05CB-Pa5-H22YYSjqKnwGyUnuFqjiawbmjVPoElIQw,3692
40
40
  vellum_ee/workflows/display/nodes/vellum/merge_node.py,sha256=jzO63B9KiEAncnBqmz2ZTcxjmEHozMEe7WnfpcpsQYg,3195
41
41
  vellum_ee/workflows/display/nodes/vellum/note_node.py,sha256=9VpC3h0RYOxJuRbjDwidBYlLKakkmlEnDMBh2C7lHcY,1107
42
- vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py,sha256=gLRkizwyw21-Z12IyDbdOJpXayiZZd4HWd6qgZQg8sc,3106
43
- vellum_ee/workflows/display/nodes/vellum/search_node.py,sha256=laNWcDt62VRM5hLfcOi-ouAyNhYiFRsD0PWbVGLwlLI,9035
42
+ vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py,sha256=3uvSVvNNwVhqxsEh4moW_gIQss1bIuw9Do8XPWr9XLA,3120
43
+ vellum_ee/workflows/display/nodes/vellum/search_node.py,sha256=sSO7n-UXoIdolRAqyKy6MdpdC-hrrt83ntSWe_qLKEM,9071
44
44
  vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py,sha256=zOp4voBSgB3MR1R93wTOrsiiara_hxEAYFupLl_SvTA,2657
45
- vellum_ee/workflows/display/nodes/vellum/templating_node.py,sha256=IHumtFFZSanRizU3-0ATFgUnDuSFZMScZce8YTDJiGU,3373
45
+ vellum_ee/workflows/display/nodes/vellum/templating_node.py,sha256=l_QDDTxHxmnwGKr6IwZZvwUMXAjSHJPNE8hf5tY75b4,3380
46
46
  vellum_ee/workflows/display/nodes/vellum/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
- vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py,sha256=aJfQnIvlrRHVKgQid_gg6VQKkJyPgFnzbvWt9_t0Vz0,3860
47
+ vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py,sha256=JPZKf7irQ38Dus5bWV_ysKkG97z0oeqP57lOptA-dPk,3881
48
48
  vellum_ee/workflows/display/nodes/vellum/try_node.py,sha256=hB8dcGMGkuC95kk9hmZUgHsCLwEA37fHTFXj0JzbRjM,4692
49
49
  vellum_ee/workflows/display/nodes/vellum/utils.py,sha256=6mPg9QilJfLw9Sgk_h9LRSyKZpKgRu06mr3X1AmmDCA,4691
50
50
  vellum_ee/workflows/display/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
51
51
  vellum_ee/workflows/display/tests/test_vellum_workflow_display.py,sha256=TEg3QbdE7rLbEhml9pMWmay--phsekGlfGVhTblxCGE,1727
52
52
  vellum_ee/workflows/display/tests/workflow_serialization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
+ vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
+ vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py,sha256=5UTzBUKC1H5ve9MJGJMMLGhQ-1ZV4NPn6wYYEdreNxM,1172
55
+ vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py,sha256=nhqi4D_6R9WtQG2WYyPy9RdoollwriWc-72BgOBY9BM,4035
53
56
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py,sha256=e__ae2yepB5vlgVT08sr1DDB8pYjax6VQLo5FtRk-nA,17934
54
57
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py,sha256=F822H2tM3Fvmc2PvunrVCRhtSKQLLpi5y2L1gyJKa78,31576
55
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py,sha256=T8gYYFd4jxOnrNp3Qhz4KH7ifvDPgyZxJJE7G9xt03U,52569
56
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py,sha256=zQ0MYjHeXR7sx4vGWEH6761DEEZ8RYMNr6ocRmLEAG0,6460
57
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py,sha256=YkgtdubGOl00kusqkADQ-YoTk6dCW83ShoV3DG9Pvuo,6182
58
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py,sha256=88z_dRc2sARwH73KqyZy6KXJCFPULdPKCeTJ2QJAODY,52192
59
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py,sha256=KNcZR9PhkXYUl-OFKc2XK9qG-C_28K01Le7ecpwPUfU,6143
60
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py,sha256=ZcKpGLZ-RyqfWzvVEsFywSYEqLHrIjFjx5RJmxJT_u4,6091
58
61
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py,sha256=vA8cd7PJYhf949OUGeYP_moKtMogSyfHN2Z-qzNQLwM,8294
59
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py,sha256=6z7WJ0GLhG7dhilenw7JTq1O8XUVeYmjJHHvgHBtQeU,21725
60
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py,sha256=iFbqXQr-4VyaqAYbldzRS4jt6G8f1Eoa1lTlMgJQO-Y,15599
61
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py,sha256=7f9sr8nv4pCqdic8E7RHDrbaOiExelIh7CZYAJ8QNus,9649
62
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py,sha256=7XaPhlX4TU7Ehq62opb_1vGHvynjxJLP_pYqyMt6IOI,22621
63
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py,sha256=lukNCF0w45X2i5SCT5KDMGFn0C0acBNY8t78sC4mBXQ,16485
64
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py,sha256=qXEVZ_OZUUvHZvQyXgVrjvhmvFp5As3DrHZWIvlhGsc,9345
62
65
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py,sha256=NkpgaTbu6nLr3iwgsSNtiHyiNDCUaFakd1JaoW6CC6Y,9489
63
66
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_serialization.py,sha256=9R6ELHBn9tsp3cy15q1qp1OByyCxFOVdrM67EwCYY50,12984
64
67
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py,sha256=8bz0vm_EyQKSjnwS5vqqgnjE9ygvm-CaPKcwCfeOrlo,12704
65
68
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py,sha256=6LrGPS7e9CWpjFq2hpliSzP9kDpZ9KqvBNlNO3sq8cs,8063
66
69
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py,sha256=xG8nKA1iKXxUe1fnD2X6qm7cUGW14iq2P-L16zhcKC8,4271
67
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py,sha256=Y_-JNnPI9nAK6cLWxGaxz9ngo0_Dr0j2VNqreFk4CtE,2659
68
- vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py,sha256=jvjQju7DYUFQ3FffVVA7RXUO0UB7-Fhq_qH7MiT0XcI,8522
69
- vellum_ee/workflows/display/types.py,sha256=FSPg3TO8iNE2gnl1vn-nsMfit2V6yeBXW0Igh089A9w,2011
70
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py,sha256=cE6dmre7LRfUV2sZReDhES1zHpYcNH07cDZCrXQsRDw,2638
71
+ vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py,sha256=stOOF7n7oZvZby9Zyk0vr7dK3OG6bx9TEaIXFEZjX0o,8478
72
+ vellum_ee/workflows/display/types.py,sha256=-ninso8Yf2EBn_RkFhpOEOjRhX2bYgCeMWssHoEgPRg,2248
70
73
  vellum_ee/workflows/display/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
71
- vellum_ee/workflows/display/utils/vellum.py,sha256=-cz3xB-_-r1O9TBdLQPBvlpptg9CrZVNQ50QimmJFnA,5032
72
- vellum_ee/workflows/display/vellum.py,sha256=OSv0ZS50h1zJbunJ9TH7VEWFw-exXdK_ZsdzPxP9ROs,8814
74
+ vellum_ee/workflows/display/utils/vellum.py,sha256=72wyR_ngYjirPYT8kFDxVPtRdHT7FpzBpsjoGMh1q0c,5053
75
+ vellum_ee/workflows/display/vellum.py,sha256=FHf2GXJ-KNXstMgRg5Prp7BL_dbUt8BSrPxg_QgJmxM,8945
73
76
  vellum_ee/workflows/display/workflows/__init__.py,sha256=kapXsC67VJcgSuiBMa86FdePG5A9kMB5Pi4Uy1O2ob4,207
74
- vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256=ydAbFMzcY2LURINZbXYm9BAXZdIa3-7rQ86Kupo7qcA,12804
75
- vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py,sha256=AMxNnTm2z3LIR5rqxoCAfuy37F2FTuSRDVtKUoezO8M,1184
76
- vellum_ee/workflows/display/workflows/vellum_workflow_display.py,sha256=GhIviEMDWNw1p8z20ta08T5PeNCVJs5p2hrOX1uyNxg,17066
77
+ vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256=u5u_KnDp_ktLBlfkT5wiGHIloodSlUT3D3_DQXijtMA,13735
78
+ vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py,sha256=kp0u8LN_2IwshLrhMImhpZx1hRyAcD5gXY-kDuuaGMQ,1269
79
+ vellum_ee/workflows/display/workflows/vellum_workflow_display.py,sha256=sUQVEP2te48G97t-au_utKfMhePi4U5nmotzMln7Ga4,16943
77
80
  vellum_ee/workflows/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
78
81
  vellum_ee/workflows/server/virtual_file_loader.py,sha256=sQQFqn7xI0GfUlypWkVFl-X5ShXTh9bXq8N6qlQvSoE,1452
79
82
  vellum/__init__.py,sha256=wO2rKMEtIjNEb53CstEj-0qkUDiKKmGb_uxXEl-jS8c,35776
@@ -81,7 +84,7 @@ vellum/client/README.md,sha256=JkCJjmMZl4jrPj46pkmL9dpK4gSzQQmP5I7z4aME4LY,4749
81
84
  vellum/client/__init__.py,sha256=7yb5YnhvHQUJusa1WyUZcAKGol3z-Lfu07EfD03eEW4,111291
82
85
  vellum/client/core/__init__.py,sha256=SQ85PF84B9MuKnBwHNHWemSGuy-g_515gFYNFhvEE0I,1438
83
86
  vellum/client/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
84
- vellum/client/core/client_wrapper.py,sha256=_Cf6x5JgwTAjYASLdfDJqsyFst0nGh8_6WqQT-DbLkk,1869
87
+ vellum/client/core/client_wrapper.py,sha256=Ip_JnKYTedcuVV4puh0iLeYLzPtHAxgnmwqZyCKXSCY,1869
85
88
  vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
86
89
  vellum/client/core/file.py,sha256=X9IbmkZmB2bB_DpmZAO3crWdXagOakAyn6UCOCImCPg,2322
87
90
  vellum/client/core/http_client.py,sha256=R0pQpCppnEtxccGvXl4uJ76s7ro_65Fo_erlNNLp_AI,19228
@@ -665,10 +668,10 @@ vellum/evaluations/utils/paginator.py,sha256=rEED_BJAXAM6tM1yMwHePNzszjq_tTq4NbQ
665
668
  vellum/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
666
669
  vellum/plugins/pydantic.py,sha256=dNtZWHo-IdseG52C2RoTanxyTJg0AhPZrH-9lbNqwYg,2604
667
670
  vellum/plugins/utils.py,sha256=U9ZY9KdE3RRvbcG01hXxu9CvfJD6Fo7nJDgcHjQn0FI,606
668
- vellum/plugins/vellum_mypy.py,sha256=VC15EzjTsXOb9uF1bky4rcxePP-0epMVmCsLB2z4Dh8,24816
671
+ vellum/plugins/vellum_mypy.py,sha256=7JmyuTX723-XWnWoE6afiUNOkHyAufCUZwxck9BP2aI,27784
669
672
  vellum/prompts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
670
673
  vellum/prompts/blocks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
671
- vellum/prompts/blocks/compilation.py,sha256=GVxV0iaVp72RCNMlLtUasfg25jBjbeEu3u97QUSbrQo,7506
674
+ vellum/prompts/blocks/compilation.py,sha256=ISuvDHaeVCPb1L7l4umORCECkDn0-rvE49hopz6c2gM,9222
672
675
  vellum/prompts/blocks/exceptions.py,sha256=vmk5PV6Vyw9nKjZYQDUDW0LH8MfQNIgFvFb_mFWdIRI,50
673
676
  vellum/prompts/blocks/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
674
677
  vellum/prompts/blocks/tests/test_compilation.py,sha256=0DhMoc4huHR6YnNL-0aBLmWSyUfw2BpRq_gEdKsQmAc,3693
@@ -1218,7 +1221,7 @@ vellum/utils/templating/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
1218
1221
  vellum/utils/templating/constants.py,sha256=XTNmDsKa7byjw4GMZmzx2dUeYUTeMLZrPgRHcc80Kvc,613
1219
1222
  vellum/utils/templating/custom_filters.py,sha256=Q0DahYRHP4KfaUXDt9XxN-DFLBrAxlv90yaVqxScoUw,264
1220
1223
  vellum/utils/templating/exceptions.py,sha256=cDp140PP4OnInW4qAvg3KqiSiF70C71UyEAKRBR1Abo,46
1221
- vellum/utils/templating/render.py,sha256=0vgkwhu2A6o64aT4fUdTSLFCEMbeRjAKAuvv2k2LYGY,1772
1224
+ vellum/utils/templating/render.py,sha256=OwdZTJlQv_qsygMX3LOFr4d1_2oz3r9vGKyj7cX05VE,1876
1222
1225
  vellum/utils/typing.py,sha256=wx_daFqD69cYkuJTVnvNrpjhqC3uuhbnyJ9_bIwC9OU,327
1223
1226
  vellum/utils/uuid.py,sha256=Ch6wWRgwICxLxJCTl5iE3EdRlZj2zADR-zUMUtjcMWM,214
1224
1227
  vellum/version.py,sha256=jq-1PlAYxN9AXuaZqbYk9ak27SgE2lw9Ia5gx1b1gVI,76
@@ -1283,7 +1286,7 @@ vellum/workflows/inputs/base.py,sha256=1kMgr0WqCYdWUqgFvgSoAMw2067FAlgwhGXLgbIOr
1283
1286
  vellum/workflows/logging.py,sha256=_a217XogktV4Ncz6xKFz7WfYmZAzkfVRVuC0rWob8ls,437
1284
1287
  vellum/workflows/nodes/__init__.py,sha256=aVdQVv7Y3Ro3JlqXGpxwaU2zrI06plDHD2aumH5WUIs,1157
1285
1288
  vellum/workflows/nodes/bases/__init__.py,sha256=cniHuz_RXdJ4TQgD8CBzoiKDiPxg62ErdVpCbWICX64,58
1286
- vellum/workflows/nodes/bases/base.py,sha256=RREFzYPxemKUvQc0NfnwQmby-p_BE3O-TbVWKbQFdfs,14271
1289
+ vellum/workflows/nodes/bases/base.py,sha256=CcWQBMR3cx5vftqQp_oJ_GncULJIbOLMyNP4KZNgU10,14487
1287
1290
  vellum/workflows/nodes/bases/base_adornment_node.py,sha256=eFTgsPCYb3eyGS0-kw7C6crFnwFx437R5wh9-8bWYts,2905
1288
1291
  vellum/workflows/nodes/bases/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1289
1292
  vellum/workflows/nodes/bases/tests/test_base_node.py,sha256=51CueFVty9XYASC0rKr1cXWejho5WElmhfhp6cCONy0,3811
@@ -1291,27 +1294,27 @@ vellum/workflows/nodes/core/__init__.py,sha256=5zDMCmyt1v0HTJzlUBwq3U9L825yZGZhT
1291
1294
  vellum/workflows/nodes/core/error_node/__init__.py,sha256=g7RRnlHhqu4qByfLjBwCunmgGA8dI5gNsjS3h6TwlSI,60
1292
1295
  vellum/workflows/nodes/core/error_node/node.py,sha256=MFHU5vITYSK-L9CuMZ49In2ZeNLWnhZD0f8r5dWvb5Y,1270
1293
1296
  vellum/workflows/nodes/core/inline_subworkflow_node/__init__.py,sha256=nKNEH1QTl-1PcvmYoqSWEl0-t6gAur8GLTXHzklRQfM,84
1294
- vellum/workflows/nodes/core/inline_subworkflow_node/node.py,sha256=zyKvpeNoD2D7vtGbNuvqXUxVgtkmSbk1XQExwX9KUf8,3602
1297
+ vellum/workflows/nodes/core/inline_subworkflow_node/node.py,sha256=XJLz7Kkk4OwrM-OcPjiLfF3XC49jDwsVKFPTNXkenvQ,3964
1295
1298
  vellum/workflows/nodes/core/inline_subworkflow_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1296
- vellum/workflows/nodes/core/inline_subworkflow_node/tests/test_node.py,sha256=99LLPgHMqohGL-G4KqOSjeVlDR_FH8Rv1gtRii85MC4,1143
1299
+ vellum/workflows/nodes/core/inline_subworkflow_node/tests/test_node.py,sha256=n0-821Ov9ZfRFX_lbzLy5o2rX8fEw2qoxz0aFWCOxVg,1547
1297
1300
  vellum/workflows/nodes/core/map_node/__init__.py,sha256=MXpZYmGfhsMJHqqlpd64WiJRtbAtAMQz-_3fCU_cLV0,56
1298
1301
  vellum/workflows/nodes/core/map_node/node.py,sha256=DTMoGqtR8MyfZ8jy8apNoN-4KFFFHywo87pfpqyBVEw,7322
1299
1302
  vellum/workflows/nodes/core/map_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1300
1303
  vellum/workflows/nodes/core/map_node/tests/test_node.py,sha256=RHSZs7t6mW3UWvRrXnHZqaXVdRT2ZquOK_YHJ-gzXsU,1871
1301
1304
  vellum/workflows/nodes/core/retry_node/__init__.py,sha256=lN2bIy5a3Uzhs_FYCrooADyYU6ZGShtvLKFWpelwPvo,60
1302
- vellum/workflows/nodes/core/retry_node/node.py,sha256=lAABgo2E_pWkzOYUBGzC1SnywgwtGuJojwT602fKCUc,3153
1305
+ vellum/workflows/nodes/core/retry_node/node.py,sha256=QEpxhKOyxDkRoAn2b0PToZWtAGQetSQYVTpb9yCOLlw,4028
1303
1306
  vellum/workflows/nodes/core/retry_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1304
- vellum/workflows/nodes/core/retry_node/tests/test_node.py,sha256=QXTnHwmJHISxXjvZMeuuEo0iVugVMJyaJoggI8yKXfI,3132
1307
+ vellum/workflows/nodes/core/retry_node/tests/test_node.py,sha256=RM_OHwxrHwyxvlQQBJPqVBxpedFuWQ9h2-Xa3kP75sc,4399
1305
1308
  vellum/workflows/nodes/core/templating_node/__init__.py,sha256=GmyuYo81_A1_Bz6id69ozVFS6FKiuDsZTiA3I6MaL2U,70
1306
1309
  vellum/workflows/nodes/core/templating_node/node.py,sha256=N-NOBd-UY91qO9orCcW4KEbhNvDQivZPA-PCxs-M0RM,4204
1307
- vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py,sha256=nW_kyJ9RAqz45_kJE_rlhOOvbV4OO3hecP-P-ydQpkw,2845
1310
+ vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py,sha256=3rN5Ncwq87Y2YKyobNXALCih6OnUTJf55otnR4V20C8,3557
1308
1311
  vellum/workflows/nodes/core/try_node/__init__.py,sha256=JVD4DrldTIqFQQFrubs9KtWCCc0YCAc7Fzol5ZWIWeM,56
1309
1312
  vellum/workflows/nodes/core/try_node/node.py,sha256=_lTmSYCiz7lktaxpNWUCglNi8_5Sfy8Rpiov5SeKVMw,3920
1310
1313
  vellum/workflows/nodes/core/try_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1311
1314
  vellum/workflows/nodes/core/try_node/tests/test_node.py,sha256=Wc2kLl-MkffsBxl3IiFaqLd16e2Iosxhk7qBnojPvQg,4092
1312
1315
  vellum/workflows/nodes/displayable/__init__.py,sha256=6F_4DlSwvHuilWnIalp8iDjjDXl0Nmz4QzJV2PYe5RI,1023
1313
1316
  vellum/workflows/nodes/displayable/api_node/__init__.py,sha256=MoxdQSnidIj1Nf_d-hTxlOxcZXaZnsWFDbE-PkTK24o,56
1314
- vellum/workflows/nodes/displayable/api_node/node.py,sha256=ehvJNkI-L_WLn8pszCaRkQuhRDgioCLaX6TT72KM_9E,2111
1317
+ vellum/workflows/nodes/displayable/api_node/node.py,sha256=ocXjg0Sp52V6DllTDZXUgOp9qBw6l_KbtWcaxowsDM4,2070
1315
1318
  vellum/workflows/nodes/displayable/bases/__init__.py,sha256=0mWIx3qUrzllV7jqt7wN03vWGMuI1WrrLZeMLT2Cl2c,304
1316
1319
  vellum/workflows/nodes/displayable/bases/api_node/__init__.py,sha256=1jwx4WC358CLA1jgzl_UD-rZmdMm2v9Mps39ndwCD7U,64
1317
1320
  vellum/workflows/nodes/displayable/bases/api_node/node.py,sha256=ywPwCxDesgnE86Wjyf2ZyG2Dr2O7xW8D4tPHZB5Se_s,2477
@@ -1412,8 +1415,8 @@ vellum/workflows/vellum_client.py,sha256=ODrq_TSl-drX2aezXegf7pizpWDVJuTXH-j6528
1412
1415
  vellum/workflows/workflows/__init__.py,sha256=KY45TqvavCCvXIkyCFMEc0dc6jTMOUci93U2DUrlZYc,66
1413
1416
  vellum/workflows/workflows/base.py,sha256=qdZYQq-jjdr0fYT0FCfmFuI5ypE3pANupgYcOqqML0o,18884
1414
1417
  vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnadGsrSZGa7t7LpJA,2008
1415
- vellum_ai-0.12.15.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1416
- vellum_ai-0.12.15.dist-info/METADATA,sha256=vXfKfASRTSAbS23j4YTI7V_hDRYglGisCWULazWGJfo,5168
1417
- vellum_ai-0.12.15.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1418
- vellum_ai-0.12.15.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1419
- vellum_ai-0.12.15.dist-info/RECORD,,
1418
+ vellum_ai-0.12.17.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1419
+ vellum_ai-0.12.17.dist-info/METADATA,sha256=01ujt39Or2zqLaKV_VsarQ9H_hkgSc1YfrsEOMokUUk,5328
1420
+ vellum_ai-0.12.17.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1421
+ vellum_ai-0.12.17.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1422
+ vellum_ai-0.12.17.dist-info/RECORD,,
vellum_cli/__init__.py CHANGED
@@ -49,6 +49,11 @@ def workflows():
49
49
  @click.option("--deployment-name", type=str, help="Unique name for the Deployment")
50
50
  @click.option("--deployment-description", type=str, help="Description for the Deployment")
51
51
  @click.option("--release-tag", type=list, help="Release Tag for the Deployment", multiple=True)
52
+ @click.option(
53
+ "--dry-run",
54
+ is_flag=True,
55
+ help="Check the Workflow for errors and expected changes, without updating its state in Vellum.",
56
+ )
52
57
  def workflows_push(
53
58
  module: Optional[str],
54
59
  deploy: Optional[bool],
@@ -56,6 +61,7 @@ def workflows_push(
56
61
  deployment_name: Optional[str],
57
62
  deployment_description: Optional[str],
58
63
  release_tag: Optional[List[str]],
64
+ dry_run: Optional[bool],
59
65
  ) -> None:
60
66
  """
61
67
  Push Workflows to Vellum. If a module is provided, only the Workflow for that module will be pushed.
@@ -69,6 +75,7 @@ def workflows_push(
69
75
  deployment_name=deployment_name,
70
76
  deployment_description=deployment_description,
71
77
  release_tags=release_tag,
78
+ dry_run=dry_run,
72
79
  )
73
80
 
74
81
 
@@ -79,6 +86,11 @@ def workflows_push(
79
86
  @click.option("--deployment-name", type=str, help="Unique name for the Deployment")
80
87
  @click.option("--deployment-description", type=str, help="Description for the Deployment")
81
88
  @click.option("--release-tag", type=list, help="Release Tag for the Deployment", multiple=True)
89
+ @click.option(
90
+ "--dry-run",
91
+ is_flag=True,
92
+ help="Check the Workflow for errors and expected changes, without updating its state in Vellum.",
93
+ )
82
94
  def push_module(
83
95
  ctx: click.Context,
84
96
  deploy: Optional[bool],
@@ -86,6 +98,7 @@ def push_module(
86
98
  deployment_name: Optional[str],
87
99
  deployment_description: Optional[str],
88
100
  release_tag: Optional[List[str]],
101
+ dry_run: Optional[bool],
89
102
  ) -> None:
90
103
  """Push a specific module to Vellum"""
91
104
 
@@ -97,6 +110,7 @@ def push_module(
97
110
  deployment_name=deployment_name,
98
111
  deployment_description=deployment_description,
99
112
  release_tags=release_tag,
113
+ dry_run=dry_run,
100
114
  )
101
115
 
102
116
 
vellum_cli/pull.py CHANGED
@@ -173,10 +173,13 @@ def pull_command(
173
173
  target.write(content)
174
174
 
175
175
  if metadata_json:
176
- workflow_config.container_image_name = metadata_json.get("runner_config", {}).get("container_image_name")
177
- workflow_config.container_image_tag = metadata_json.get("runner_config", {}).get("container_image_tag")
178
- if workflow_config.container_image_name and not workflow_config.container_image_tag:
179
- workflow_config.container_image_tag = "latest"
176
+ runner_config = metadata_json.get("runner_config")
177
+
178
+ if runner_config:
179
+ workflow_config.container_image_name = runner_config.get("container_image_name")
180
+ workflow_config.container_image_tag = runner_config.get("container_image_tag")
181
+ if workflow_config.container_image_name and not workflow_config.container_image_tag:
182
+ workflow_config.container_image_tag = "latest"
180
183
 
181
184
  if include_json:
182
185
  logger.warning(
vellum_cli/push.py CHANGED
@@ -27,6 +27,7 @@ def push_command(
27
27
  deployment_name: Optional[str] = None,
28
28
  deployment_description: Optional[str] = None,
29
29
  release_tags: Optional[List[str]] = None,
30
+ dry_run: Optional[bool] = None,
30
31
  ) -> None:
31
32
  load_dotenv()
32
33
  logger = load_cli_logger()
@@ -49,7 +50,11 @@ def push_command(
49
50
  # Remove this once we could serialize using the artifact in Vembda
50
51
  # https://app.shortcut.com/vellum/story/5585
51
52
  workflow = BaseWorkflow.load_from_module(workflow_config.module)
52
- workflow_display = get_workflow_display(base_display_class=VellumWorkflowDisplay, workflow_class=workflow)
53
+ workflow_display = get_workflow_display(
54
+ base_display_class=VellumWorkflowDisplay,
55
+ workflow_class=workflow,
56
+ dry_run=dry_run or False,
57
+ )
53
58
  exec_config = workflow_display.serialize()
54
59
 
55
60
  container_tag = workflow_config.container_image_tag
@@ -114,11 +119,28 @@ def push_command(
114
119
  # We should check with fern if we could auto-serialize typed object fields for us
115
120
  # https://app.shortcut.com/vellum/story/5568
116
121
  deployment_config=deployment_config_serialized, # type: ignore[arg-type]
122
+ dry_run=dry_run,
117
123
  )
118
- logger.info(
119
- f"""Successfully pushed {label} to Vellum!
124
+
125
+ if dry_run:
126
+ error_messages = [str(e) for e in workflow_display.errors]
127
+ error_message = "\n".join(error_messages) if error_messages else "No errors found."
128
+ logger.info(
129
+ f"""\
130
+ # Workflow Push Report
131
+
132
+ ## Errors
133
+ {error_message}
134
+
135
+ ## Proposed Diffs
136
+ {json.dumps(response.proposed_diffs, indent=2)}
137
+ """
138
+ ) # type: ignore[attr-defined]
139
+ else:
140
+ logger.info(
141
+ f"""Successfully pushed {label} to Vellum!
120
142
  Visit at: https://app.vellum.ai/workflow-sandboxes/{response.workflow_sandbox_id}"""
121
- )
143
+ )
122
144
 
123
145
  requires_save = False
124
146
  if not workflow_config.workflow_sandbox_id:
@@ -18,11 +18,13 @@ class MockModuleResult:
18
18
 
19
19
 
20
20
  @pytest.fixture
21
- def mock_module() -> Generator[MockModuleResult, None, None]:
21
+ def mock_module(request) -> Generator[MockModuleResult, None, None]:
22
22
  current_dir = os.getcwd()
23
23
  temp_dir = tempfile.mkdtemp()
24
24
  os.chdir(temp_dir)
25
- module = "examples.mock"
25
+
26
+ # Use the test name to create a unique module path
27
+ module = f"examples.mock.{request.node.name}"
26
28
  workflow_sandbox_id = str(uuid4())
27
29
 
28
30
  def set_pyproject_toml(vellum_config: Dict[str, Any]) -> None:
@@ -110,13 +110,17 @@ class ExampleWorkflow(BaseWorkflow):
110
110
  # THEN it should succeed
111
111
  assert result.exit_code == 0
112
112
 
113
+ # Get the last part of the module path and format it
114
+ expected_label = mock_module.module.split(".")[-1].replace("_", " ").title()
115
+ expected_artifact_name = f"{mock_module.module.replace('.', '__')}.tar.gz"
116
+
113
117
  # AND we should have called the push API with the correct args
114
118
  vellum_client.workflows.push.assert_called_once()
115
119
  call_args = vellum_client.workflows.push.call_args.kwargs
116
120
  assert json.loads(call_args["exec_config"])["workflow_raw_data"]["definition"]["name"] == "ExampleWorkflow"
117
- assert call_args["label"] == "Mock"
121
+ assert call_args["label"] == expected_label
118
122
  assert is_valid_uuid(call_args["workflow_sandbox_id"])
119
- assert call_args["artifact"].name == "examples__mock.tar.gz"
123
+ assert call_args["artifact"].name == expected_artifact_name
120
124
  assert "deplyment_config" not in call_args
121
125
 
122
126
  extracted_files = _extract_tar_gz(call_args["artifact"].read())
@@ -160,14 +164,81 @@ class ExampleWorkflow(BaseWorkflow):
160
164
  # THEN it should succeed
161
165
  assert result.exit_code == 0
162
166
 
167
+ # Get the last part of the module path and format it
168
+ expected_label = mock_module.module.split(".")[-1].replace("_", " ").title()
169
+ expected_artifact_name = f"{mock_module.module.replace('.', '__')}.tar.gz"
170
+
163
171
  # AND we should have called the push API with the correct args
164
172
  vellum_client.workflows.push.assert_called_once()
165
173
  call_args = vellum_client.workflows.push.call_args.kwargs
166
174
  assert json.loads(call_args["exec_config"])["workflow_raw_data"]["definition"]["name"] == "ExampleWorkflow"
167
- assert call_args["label"] == "Mock"
175
+ assert call_args["label"] == expected_label
168
176
  assert is_valid_uuid(call_args["workflow_sandbox_id"])
169
- assert call_args["artifact"].name == "examples__mock.tar.gz"
177
+ assert call_args["artifact"].name == expected_artifact_name
170
178
  assert call_args["deployment_config"] == "{}"
171
179
 
172
180
  extracted_files = _extract_tar_gz(call_args["artifact"].read())
173
181
  assert extracted_files["workflow.py"] == workflow_py_file_content
182
+
183
+
184
+ def test_push__dry_run_option_returns_report(mock_module, vellum_client):
185
+ # GIVEN a single workflow configured
186
+ temp_dir = mock_module.temp_dir
187
+ module = mock_module.module
188
+
189
+ # AND a workflow exists in the module successfully
190
+ base_dir = os.path.join(temp_dir, *module.split("."))
191
+ os.makedirs(base_dir, exist_ok=True)
192
+ workflow_py_file_content = """\
193
+ from typing import Dict
194
+ from vellum.workflows import BaseWorkflow
195
+ from vellum.workflows.nodes import BaseNode
196
+ from vellum_ee.workflows.display.nodes import BaseNodeDisplay
197
+
198
+ class NotSupportedNode(BaseNode):
199
+ pass
200
+
201
+ class NotSupportedNodeDisplay(BaseNodeDisplay[NotSupportedNode]):
202
+ def serialize(self, display_context, **kwargs) -> Dict:
203
+ raise NotImplementedError(f"Serialization is not supported.")
204
+
205
+ class ExampleWorkflow(BaseWorkflow):
206
+ graph = NotSupportedNode
207
+ """
208
+ with open(os.path.join(temp_dir, *module.split("."), "workflow.py"), "w") as f:
209
+ f.write(workflow_py_file_content)
210
+
211
+ # AND the push API call returns successfully
212
+ vellum_client.workflows.push.return_value = WorkflowPushResponse(
213
+ workflow_sandbox_id=str(uuid4()),
214
+ proposed_diffs={
215
+ "iterable_item_added": {
216
+ "root['raw_data']['nodes'][0]": {
217
+ "id": str(uuid4()),
218
+ "type": "GENERIC",
219
+ "definition": None,
220
+ "display_data": None,
221
+ "trigger": {"id": str(uuid4()), "merge_behavior": "AWAIT_ATTRIBUTES"},
222
+ "ports": [{"id": str(uuid4()), "name": "default", "type": "DEFAULT"}],
223
+ },
224
+ },
225
+ },
226
+ )
227
+
228
+ # WHEN calling `vellum push`
229
+ runner = CliRunner(mix_stderr=True)
230
+ result = runner.invoke(cli_main, ["push", module, "--dry-run"])
231
+
232
+ # THEN it should succeed
233
+ assert result.exit_code == 0
234
+
235
+ # AND we should have called the push API with the dry-run option
236
+ vellum_client.workflows.push.assert_called_once()
237
+ call_args = vellum_client.workflows.push.call_args.kwargs
238
+ assert call_args["dry_run"] is True
239
+
240
+ # AND the report should be in the output
241
+ assert "## Errors" in result.output
242
+ assert "Serialization is not supported." in result.output
243
+ assert "## Proposed Diffs" in result.output
244
+ assert "iterable_item_added" in result.output
@@ -161,9 +161,9 @@ class BaseAPINodeDisplay(BaseNodeVellumDisplay[_APINodeType], Generic[_APINodeTy
161
161
  ]
162
162
  inputs.extend(additional_header_inputs)
163
163
 
164
- _, text_output_display = display_context.node_output_displays[cast(OutputReference, node.Outputs.text)]
165
- _, json_output_display = display_context.node_output_displays[cast(OutputReference, node.Outputs.json)]
166
- _, status_code_output_display = display_context.node_output_displays[
164
+ _, text_output_display = display_context.global_node_output_displays[cast(OutputReference, node.Outputs.text)]
165
+ _, json_output_display = display_context.global_node_output_displays[cast(OutputReference, node.Outputs.json)]
166
+ _, status_code_output_display = display_context.global_node_output_displays[
167
167
  cast(OutputReference, node.Outputs.status_code)
168
168
  ]
169
169
 
@@ -2,17 +2,34 @@ from typing import Any, Generic, TypeVar
2
2
 
3
3
  from vellum.workflows.nodes.bases.base import BaseNode
4
4
  from vellum.workflows.types.core import JsonObject
5
+ from vellum.workflows.utils.uuids import uuid4_from_hash
5
6
  from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
6
7
  from vellum_ee.workflows.display.types import WorkflowDisplayContext
8
+ from vellum_ee.workflows.display.vellum import GenericNodeDisplayData
7
9
 
8
10
  _BaseNodeType = TypeVar("_BaseNodeType", bound=BaseNode)
9
11
 
10
12
 
11
13
  class BaseNodeDisplay(BaseNodeVellumDisplay[_BaseNodeType], Generic[_BaseNodeType]):
12
14
  def serialize(self, display_context: WorkflowDisplayContext, **kwargs: Any) -> JsonObject:
15
+ node = self._node
13
16
  node_id = self.node_id
14
17
 
15
18
  return {
16
19
  "id": str(node_id),
20
+ "label": node.__qualname__,
17
21
  "type": "GENERIC",
22
+ "display_data": self.get_generic_node_display_data().dict(),
23
+ "definition": self.get_definition().dict(),
24
+ "trigger": {
25
+ "id": str(uuid4_from_hash(f"{node_id}|trigger")),
26
+ "merge_behavior": node.Trigger.merge_behavior.value,
27
+ },
28
+ "ports": [],
29
+ "adornments": None,
30
+ "attributes": [],
18
31
  }
32
+
33
+ def get_generic_node_display_data(self) -> GenericNodeDisplayData:
34
+ explicit_value = self._get_explicit_node_display_attr("display_data", GenericNodeDisplayData)
35
+ return explicit_value if explicit_value else GenericNodeDisplayData()
@@ -70,8 +70,8 @@ class BaseCodeExecutionNodeDisplay(BaseNodeVellumDisplay[_CodeExecutionNodeType]
70
70
 
71
71
  packages = raise_if_descriptor(node.packages)
72
72
 
73
- _, output_display = display_context.node_output_displays[node.Outputs.result]
74
- _, log_output_display = display_context.node_output_displays[node.Outputs.log]
73
+ _, output_display = display_context.global_node_output_displays[node.Outputs.result]
74
+ _, log_output_display = display_context.global_node_output_displays[node.Outputs.log]
75
75
 
76
76
  output_type = primitive_type_to_vellum_variable_type(node.get_output_type())
77
77
 
@@ -29,8 +29,8 @@ class BaseInlinePromptNodeDisplay(BaseNodeVellumDisplay[_InlinePromptNodeType],
29
29
  node_inputs, prompt_inputs = self._generate_node_and_prompt_inputs(node_id, node, display_context)
30
30
  input_variable_id_by_name = {prompt_input.key: prompt_input.id for prompt_input in prompt_inputs}
31
31
 
32
- _, output_display = display_context.node_output_displays[node.Outputs.text]
33
- _, array_display = display_context.node_output_displays[node.Outputs.results]
32
+ _, output_display = display_context.global_node_output_displays[node.Outputs.text]
33
+ _, array_display = display_context.global_node_output_displays[node.Outputs.results]
34
34
  node_blocks = raise_if_descriptor(node.blocks)
35
35
 
36
36
  return {
@@ -2,6 +2,7 @@ from uuid import UUID
2
2
  from typing import ClassVar, Dict, Generic, List, Optional, Tuple, Type, TypeVar, cast
3
3
 
4
4
  from vellum import VellumVariable
5
+ from vellum.workflows.inputs.base import BaseInputs
5
6
  from vellum.workflows.nodes import InlineSubworkflowNode
6
7
  from vellum.workflows.types.core import JsonObject
7
8
  from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
@@ -60,12 +61,25 @@ class BaseInlineSubworkflowNodeDisplay(
60
61
  node: Type[InlineSubworkflowNode],
61
62
  display_context: WorkflowDisplayContext,
62
63
  ) -> Tuple[List[NodeInput], List[VellumVariable]]:
64
+ subworkflow = raise_if_descriptor(node.subworkflow)
65
+ subworkflow_inputs_class = subworkflow.get_inputs_class()
63
66
  subworkflow_inputs = raise_if_descriptor(node.subworkflow_inputs)
64
- subworkflow_entries = (
65
- [(variable_name, variable_value) for variable_name, variable_value in subworkflow_inputs.items()]
66
- if isinstance(subworkflow_inputs, dict)
67
- else [(variable_ref.name, variable_value) for variable_ref, variable_value in subworkflow_inputs]
68
- )
67
+
68
+ if isinstance(subworkflow_inputs, BaseInputs):
69
+ subworkflow_entries = [
70
+ (variable_ref.name, variable_value) for variable_ref, variable_value in subworkflow_inputs
71
+ ]
72
+ elif isinstance(subworkflow_inputs, dict):
73
+ subworkflow_entries = [
74
+ (variable_name, variable_value) for variable_name, variable_value in subworkflow_inputs.items()
75
+ ]
76
+ else:
77
+ subworkflow_entries = [
78
+ (descriptor.name, getattr(subworkflow_inputs_class, descriptor.name))
79
+ for descriptor in subworkflow_inputs_class
80
+ if hasattr(subworkflow_inputs_class, descriptor.name)
81
+ ]
82
+
69
83
  node_inputs = [
70
84
  create_node_input(
71
85
  node_id=node_id,
@@ -83,7 +97,7 @@ class BaseInlineSubworkflowNodeDisplay(
83
97
  key=descriptor.name,
84
98
  type=infer_vellum_variable_type(descriptor),
85
99
  )
86
- for descriptor in raise_if_descriptor(node.subworkflow).get_inputs_class()
100
+ for descriptor in subworkflow_inputs_class
87
101
  ]
88
102
 
89
103
  return node_inputs, workflow_inputs
@@ -33,6 +33,7 @@ class BaseMapNodeDisplay(BaseNodeVellumDisplay[_MapNodeType], Generic[_MapNodeTy
33
33
  subworkflow_display = get_workflow_display(
34
34
  base_display_class=display_context.workflow_display_class,
35
35
  workflow_class=subworkflow,
36
+ parent_display_context=display_context,
36
37
  )
37
38
  serialized_subworkflow = subworkflow_display.serialize()
38
39
 
@@ -38,8 +38,8 @@ class BasePromptDeploymentNodeDisplay(
38
38
  for variable_name, variable_value in prompt_inputs.items()
39
39
  ]
40
40
 
41
- _, output_display = display_context.node_output_displays[cast(OutputReference, node.Outputs.text)]
42
- _, array_display = display_context.node_output_displays[cast(OutputReference, node.Outputs.results)]
41
+ _, output_display = display_context.global_node_output_displays[cast(OutputReference, node.Outputs.text)]
42
+ _, array_display = display_context.global_node_output_displays[cast(OutputReference, node.Outputs.results)]
43
43
 
44
44
  # TODO: Pass through the name instead of retrieving the ID
45
45
  # https://app.shortcut.com/vellum/story/4702
@@ -39,8 +39,10 @@ class BaseSearchNodeDisplay(BaseNodeVellumDisplay[_SearchNodeType], Generic[_Sea
39
39
  node_id = self.node_id
40
40
  node_inputs = self._generate_search_node_inputs(node_id, node, display_context)
41
41
 
42
- _, results_output_display = display_context.node_output_displays[cast(OutputReference, node.Outputs.results)]
43
- _, text_output_display = display_context.node_output_displays[cast(OutputReference, node.Outputs.text)]
42
+ _, results_output_display = display_context.global_node_output_displays[
43
+ cast(OutputReference, node.Outputs.results)
44
+ ]
45
+ _, text_output_display = display_context.global_node_output_displays[cast(OutputReference, node.Outputs.text)]
44
46
 
45
47
  return {
46
48
  "id": str(node_id),
@@ -56,7 +56,7 @@ class BaseTemplatingNodeDisplay(BaseNodeVellumDisplay[_TemplatingNodeType], Gene
56
56
  # Misc type ignore is due to `node.Outputs` being generic
57
57
  # https://app.shortcut.com/vellum/story/4784
58
58
  output_descriptor = node.Outputs.result # type: ignore [misc]
59
- _, output_display = display_context.node_output_displays[output_descriptor]
59
+ _, output_display = display_context.global_node_output_displays[output_descriptor]
60
60
  inferred_output_type = primitive_type_to_vellum_variable_type(output_descriptor)
61
61
 
62
62
  return {