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

Sign up to get free protection for your applications and to get access to all the features.
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 {