vellum-ai 0.13.14__py3-none-any.whl → 0.13.18__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 (26) hide show
  1. vellum/client/core/client_wrapper.py +1 -1
  2. vellum/client/resources/workflows/client.py +0 -10
  3. vellum/workflows/nodes/core/templating_node/node.py +4 -47
  4. vellum/workflows/nodes/displayable/code_execution_node/node.py +29 -23
  5. vellum/workflows/nodes/displayable/code_execution_node/tests/test_code_execution_node.py +169 -5
  6. vellum/workflows/nodes/displayable/code_execution_node/utils.py +98 -1
  7. vellum/workflows/nodes/utils.py +50 -1
  8. vellum/workflows/references/external_input.py +14 -0
  9. vellum/workflows/state/base.py +7 -0
  10. vellum/workflows/state/tests/test_state.py +42 -0
  11. {vellum_ai-0.13.14.dist-info → vellum_ai-0.13.18.dist-info}/METADATA +1 -1
  12. {vellum_ai-0.13.14.dist-info → vellum_ai-0.13.18.dist-info}/RECORD +26 -25
  13. vellum_cli/__init__.py +11 -0
  14. vellum_cli/pull.py +57 -20
  15. vellum_cli/push.py +27 -10
  16. vellum_cli/tests/test_pull.py +115 -8
  17. vellum_cli/tests/test_push.py +148 -44
  18. vellum_ee/workflows/display/nodes/base_node_display.py +2 -2
  19. vellum_ee/workflows/display/nodes/get_node_display_class.py +16 -20
  20. vellum_ee/workflows/display/nodes/vellum/__init__.py +2 -0
  21. vellum_ee/workflows/display/nodes/vellum/retry_node.py +10 -0
  22. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +23 -0
  23. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +2 -2
  24. {vellum_ai-0.13.14.dist-info → vellum_ai-0.13.18.dist-info}/LICENSE +0 -0
  25. {vellum_ai-0.13.14.dist-info → vellum_ai-0.13.18.dist-info}/WHEEL +0 -0
  26. {vellum_ai-0.13.14.dist-info → vellum_ai-0.13.18.dist-info}/entry_points.txt +0 -0
@@ -64,6 +64,22 @@ def test_state_snapshot__nested_dictionary_edit():
64
64
  assert snapshot_count[id(state)] == 1
65
65
 
66
66
 
67
+ def test_state_snapshot__external_input_edit():
68
+ # GIVEN an initial state instance
69
+ state = MockState(foo="bar")
70
+ assert snapshot_count[id(state)] == 0
71
+
72
+ # WHEN we add an external input to state
73
+ class MockExternalInputs(BaseNode.ExternalInputs):
74
+ message: str
75
+
76
+ # WHEN we edit external inputs dictionary
77
+ state.meta.external_inputs[MockExternalInputs.message] = "hello"
78
+
79
+ # THEN the snapshot is emitted
80
+ assert snapshot_count[id(state)] == 1
81
+
82
+
67
83
  def test_state_deepcopy():
68
84
  # GIVEN an initial state instance
69
85
  state = MockState(foo="bar")
@@ -116,6 +132,32 @@ def test_state_json_serialization__with_node_output_updates():
116
132
  assert json_state["meta"]["node_outputs"] == {"MockNode.Outputs.baz": "hello"}
117
133
 
118
134
 
135
+ def test_state_deepcopy__with_external_input_updates():
136
+ # GIVEN an initial state instance
137
+ state = MockState(foo="bar")
138
+
139
+ # AND we add an external input to state
140
+ class MockExternalInputs(BaseNode.ExternalInputs):
141
+ message: str
142
+
143
+ state.meta.external_inputs[MockExternalInputs.message] = "hello"
144
+
145
+ # AND we deepcopy the state
146
+ deepcopied_state = deepcopy(state)
147
+
148
+ # AND we update the original state
149
+ state.meta.external_inputs[MockExternalInputs.message] = "world"
150
+
151
+ # THEN the copied state is not updated
152
+ assert deepcopied_state.meta.external_inputs[MockExternalInputs.message] == "hello"
153
+
154
+ # AND the original state has had the correct number of snapshots
155
+ assert snapshot_count[id(state)] == 2
156
+
157
+ # AND the copied state has had the correct number of snapshots
158
+ assert snapshot_count[id(deepcopied_state)] == 0
159
+
160
+
119
161
  def test_state_json_serialization__with_queue():
120
162
  # GIVEN an initial state instance
121
163
  state = MockState(foo="bar")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vellum-ai
3
- Version: 0.13.14
3
+ Version: 0.13.18
4
4
  Summary:
5
5
  License: MIT
6
6
  Requires-Python: >=3.9,<4.0
@@ -1,34 +1,34 @@
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=tRcOi6oLzT3EXORlHwGzo0Sn1-npf8Jf7mMi90NDUh0,10035
3
+ vellum_cli/__init__.py,sha256=uEn2Nlt2Z0kBc79NcO4-rgOIE7H9nsMEEjWF6MLDlPo,10591
4
4
  vellum_cli/aliased_group.py,sha256=ugW498j0yv4ALJ8vS9MsO7ctDW7Jlir9j6nE_uHAP8c,3363
5
5
  vellum_cli/config.py,sha256=LVRB-SEJcpQYfg2QGcjKHmRSAijdSFADbS90gDY4AI8,6829
6
6
  vellum_cli/image_push.py,sha256=SJwhwWJsLjwGNezNVd_oCVpFMfPsAB3dfLWmriZZUtw,4419
7
7
  vellum_cli/logger.py,sha256=PuRFa0WCh4sAGFS5aqWB0QIYpS6nBWwPJrIXpWxugV4,1022
8
8
  vellum_cli/ping.py,sha256=lWyJw6sziXjyTopTYRdFF5hV-sYPVDdX0yVbG5fzcY4,585
9
- vellum_cli/pull.py,sha256=zf0y22XptUYI_hMP_4Q1CEo9s2wALsTJcCXNd-_ibd8,7551
10
- vellum_cli/push.py,sha256=0Q3Of25KzqDq0KTgkXQ22nAhSH4_JI424hKwKkj3RWs,8627
9
+ vellum_cli/pull.py,sha256=7yvg4oBOgsbBEsgXtCpYlNR4AOR8hPICamY-4HI-3kM,9031
10
+ vellum_cli/push.py,sha256=qQCI_cHvVjeDGA8FLYmSN7UE_wIJQnUXX_5cGsm9OTs,9076
11
11
  vellum_cli/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
12
  vellum_cli/tests/conftest.py,sha256=AFYZryKA2qnUuCPBxBKmHLFoPiE0WhBFFej9tNwSHdc,1526
13
13
  vellum_cli/tests/test_config.py,sha256=uvKGDc8BoVyT9_H0Z-g8469zVxomn6Oi3Zj-vK7O_wU,2631
14
14
  vellum_cli/tests/test_main.py,sha256=qDZG-aQauPwBwM6A2DIu1494n47v3pL28XakTbLGZ-k,272
15
15
  vellum_cli/tests/test_ping.py,sha256=QtbhYKMYn1DFnDyBij2mkQO32j9KOpZ5Pf0yek7k_Ao,1284
16
- vellum_cli/tests/test_pull.py,sha256=KRvQ_fwsFH6tBU49O-KOOAzcHxdB-DPbUkdIdahjuTs,19841
17
- vellum_cli/tests/test_push.py,sha256=3to7bOOVoWB888ee7TIAVl2VgXCsJhP_aPcrXwF9c_c,14023
16
+ vellum_cli/tests/test_pull.py,sha256=CEnVpb9i-_I0wOSabjgJxleRuvvAHFfDB0_f4CvpwMI,23742
17
+ vellum_cli/tests/test_push.py,sha256=kcM8jp6vTRBwfk6cAC_tHa4Eliuy_zZ-X1DfIpSEIW0,18299
18
18
  vellum_ee/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  vellum_ee/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
20
  vellum_ee/workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  vellum_ee/workflows/display/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  vellum_ee/workflows/display/base.py,sha256=3ZFUYRNKL24fBqXhKpa_Dq2W1a-a86J20dmJYA3H2eY,1755
23
23
  vellum_ee/workflows/display/nodes/__init__.py,sha256=5XOcZJXYUgaLS55QgRJzyQ_W1tpeprjnYAeYVezqoGw,160
24
- vellum_ee/workflows/display/nodes/base_node_display.py,sha256=YBXHPwf453j-xaJoeJsoGhnW039WPSmhbQO-G5UGtcY,15787
24
+ vellum_ee/workflows/display/nodes/base_node_display.py,sha256=ErIK_1DYax0LlFX4AvV1oua8I7JlpXNncjGNadVe-bo,15801
25
25
  vellum_ee/workflows/display/nodes/base_node_vellum_display.py,sha256=pLO0dORfRu--Ne9NgoyFT_CNjfpr5fGCsgbsMkUF5GM,2845
26
- vellum_ee/workflows/display/nodes/get_node_display_class.py,sha256=VpGL-tnMM9wEOkuHNxX74RHAFhz5jcVXvmBkKciOBg0,1367
26
+ vellum_ee/workflows/display/nodes/get_node_display_class.py,sha256=0S6ksPp53WXWh1RQVH71nj2bkCWBj4ZaFYhTxW3N2F4,1230
27
27
  vellum_ee/workflows/display/nodes/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
28
  vellum_ee/workflows/display/nodes/tests/test_base_node_display.py,sha256=QqR3Ly0RNrXwOeLdW5nERDFt0gRPf76n1bPES6o5UN4,1093
29
29
  vellum_ee/workflows/display/nodes/types.py,sha256=St1BB6no528OyELGiyRabWao0GGw6mLhstQAvEACbGk,247
30
30
  vellum_ee/workflows/display/nodes/utils.py,sha256=sloya5TpXsnot1HURc9L51INwflRqUzHxRVnCS9Cd-4,973
31
- vellum_ee/workflows/display/nodes/vellum/__init__.py,sha256=nmPLj8vkbVCS46XQqmHq8Xj8Mr36wCK_vWf26A9KIkw,1505
31
+ vellum_ee/workflows/display/nodes/vellum/__init__.py,sha256=Moeuvm0u7c_6wtxUWOJqTJYbrnG4Rp_5mKRoYpfewvQ,1578
32
32
  vellum_ee/workflows/display/nodes/vellum/api_node.py,sha256=hoV-cUtS6H9kmRQXHd2py95GRWI_dAnnaPwvlNBkDOQ,8571
33
33
  vellum_ee/workflows/display/nodes/vellum/code_execution_node.py,sha256=z00Z3L0d4PsUQo4S8FRDTtOFLtjdi17TJbatNVF4nM8,4288
34
34
  vellum_ee/workflows/display/nodes/vellum/conditional_node.py,sha256=ybLIa4uclqVIy3VAQvI1ivg2tnK5Ug_1R5a69DFqL7E,11104
@@ -41,6 +41,7 @@ vellum_ee/workflows/display/nodes/vellum/map_node.py,sha256=VlO3UwkspCOdDQ-h3v8k
41
41
  vellum_ee/workflows/display/nodes/vellum/merge_node.py,sha256=HkNMgdQELiON42jdO-xDLmqrEKdGx1RVqrz2DXNTLS8,3239
42
42
  vellum_ee/workflows/display/nodes/vellum/note_node.py,sha256=TMb8txILu2uWjzoxaghjgjlzeBAgzn4vkP_8zSh2qoE,1151
43
43
  vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py,sha256=LFjLUrH6sJ4czPnExdRqFr0PB_yKBMLXLvK5GAzIAgc,3273
44
+ vellum_ee/workflows/display/nodes/vellum/retry_node.py,sha256=i0XGbKecLiHtf7mBf2rbqldPgLcs1TitIphzcHRIvkA,341
44
45
  vellum_ee/workflows/display/nodes/vellum/search_node.py,sha256=TxcAGZDl_hvJ7Y1hUi9YVEVrj9Ie0hKkASdpfRL4_cs,9227
45
46
  vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py,sha256=lfevlHpGEX14dEDym6qmnkw3nvzQPTB1_D2ch12B_Rk,2701
46
47
  vellum_ee/workflows/display/nodes/vellum/templating_node.py,sha256=JVIMPR3WpveOCWZubHKZkE04mavnTdb_9QY_r3XliRg,3424
@@ -55,13 +56,13 @@ vellum_ee/workflows/display/tests/test_vellum_workflow_display.py,sha256=h4bE187
55
56
  vellum_ee/workflows/display/tests/workflow_serialization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
57
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
58
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py,sha256=EenmEdBtHUFQ0OS-kE7Vboax3JnDdj-K4Qixt5oR0Po,2253
58
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py,sha256=pYBubuTzwNczAGFTYhaMCwvMLAcoJfCLkn5PMPbrlMI,7187
59
+ vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py,sha256=6wgLNd-Ae-33SPIYhOvQ9KJ8-5ach98v_Z3g7nrN_xs,8026
59
60
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py,sha256=yPXhdZxEDunNl5LL5Obb0jeO34djt7F-GiaTJhp_fmo,16742
60
61
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py,sha256=-12ZkZb3f5gyoNASV2yeQtMo5HmNsVEo8nXwL6IC-I8,6261
61
62
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py,sha256=6th6kCwzql6lddjkTQx4Jbvvs4ChqtJwctW-B4QuBhI,37352
62
63
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py,sha256=EbVgg_3_ipTt3MOop4RARX0fmNjwqZtkhIXzx9nGw7Y,4487
63
64
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py,sha256=bXZWxOKAVjZlbP3iLHPHGA4aPs0EguKlQqmYPNGv3cU,16391
64
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py,sha256=uvABhpstyxNNOz50-XJMAr3SKp8gluPp1mUtJjvRL0c,29410
65
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py,sha256=s2mBoL5Vvpoc-rcWcSGQjLp4yzVVwFmkTbS3--ErzCI,29486
65
66
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py,sha256=n3F_Eyru0DYOszBH4jplz7Mzt2FfBNxGlCkTFqvrX-M,48399
66
67
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py,sha256=8LhQgW0uzVOhzz0AwdM-EYugVO-0mGWglxWo_lON4D8,6079
67
68
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py,sha256=yWDykoHUjuiVYdevcJxWmYDDmbIszpHKYBu19vqR-I8,5746
@@ -112,7 +113,7 @@ vellum/client/README.md,sha256=JkCJjmMZl4jrPj46pkmL9dpK4gSzQQmP5I7z4aME4LY,4749
112
113
  vellum/client/__init__.py,sha256=8nZt88C9SVwWanjLbIQMU3rzb32h5UZfFMBx3VPHB50,111887
113
114
  vellum/client/core/__init__.py,sha256=SQ85PF84B9MuKnBwHNHWemSGuy-g_515gFYNFhvEE0I,1438
114
115
  vellum/client/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
115
- vellum/client/core/client_wrapper.py,sha256=WBZxe9jwGagoDy-B3qFt1xxFJYUu4kED2-27248SBsQ,1869
116
+ vellum/client/core/client_wrapper.py,sha256=JapYtCCqy-ryd-fk1i1krQS6K630bgNpUw4zE0Lct8s,1869
116
117
  vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
117
118
  vellum/client/core/file.py,sha256=X9IbmkZmB2bB_DpmZAO3crWdXagOakAyn6UCOCImCPg,2322
118
119
  vellum/client/core/http_client.py,sha256=R0pQpCppnEtxccGvXl4uJ76s7ro_65Fo_erlNNLp_AI,19228
@@ -168,7 +169,7 @@ vellum/client/resources/workflow_deployments/types/workflow_deployments_list_req
168
169
  vellum/client/resources/workflow_sandboxes/__init__.py,sha256=FTtvy8EDg9nNNg9WCatVgKTRYV8-_v1roeGPAKoa_pw,65
169
170
  vellum/client/resources/workflow_sandboxes/client.py,sha256=3wVQxkjrJ5bIS8fB5FpKXCP2dX38299ghWrJ8YmXxwQ,7435
170
171
  vellum/client/resources/workflows/__init__.py,sha256=Z4xi8Nxd9U4t35FQSepTt1p-ns0X1xtdNs168kUcuBk,153
171
- vellum/client/resources/workflows/client.py,sha256=9y2Tak0kduS0D1yu57FlgvV_svJZzJlRbGTJ6bz-QuA,11419
172
+ vellum/client/resources/workflows/client.py,sha256=hM7FDn05XHhQk599ti8CI4moIg0RVoEFil3Wp9v9UZk,11215
172
173
  vellum/client/resources/workflows/types/__init__.py,sha256=-uFca4ypncAOvfsg6sjD-5C9zWdA5qNvU6m675GphVg,177
173
174
  vellum/client/resources/workflows/types/workflows_pull_request_format.py,sha256=dOWE_jnDnniIJLoeseeCms23aklghyBkoPmBFzcqqZk,165
174
175
  vellum/client/resources/workspace_secrets/__init__.py,sha256=FTtvy8EDg9nNNg9WCatVgKTRYV8-_v1roeGPAKoa_pw,65
@@ -1326,7 +1327,7 @@ vellum/workflows/nodes/core/retry_node/node.py,sha256=QEpxhKOyxDkRoAn2b0PToZWtAG
1326
1327
  vellum/workflows/nodes/core/retry_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1327
1328
  vellum/workflows/nodes/core/retry_node/tests/test_node.py,sha256=RM_OHwxrHwyxvlQQBJPqVBxpedFuWQ9h2-Xa3kP75sc,4399
1328
1329
  vellum/workflows/nodes/core/templating_node/__init__.py,sha256=GmyuYo81_A1_Bz6id69ozVFS6FKiuDsZTiA3I6MaL2U,70
1329
- vellum/workflows/nodes/core/templating_node/node.py,sha256=GxsVS1FoV84kOtluu00V8H74MEnYvEf55p8mt4ub-5w,5188
1330
+ vellum/workflows/nodes/core/templating_node/node.py,sha256=zCYhq88qLTvoC9LetVrD9sLXkwHZsaWekxMhru_nV70,3752
1330
1331
  vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py,sha256=5iZWQWdJKDHMXBY8bhpb-Dpy9FTfW1HXxGUTivykZAA,4621
1331
1332
  vellum/workflows/nodes/core/try_node/__init__.py,sha256=JVD4DrldTIqFQQFrubs9KtWCCc0YCAc7Fzol5ZWIWeM,56
1332
1333
  vellum/workflows/nodes/core/try_node/node.py,sha256=_lTmSYCiz7lktaxpNWUCglNi8_5Sfy8Rpiov5SeKVMw,3920
@@ -1350,12 +1351,12 @@ vellum/workflows/nodes/displayable/bases/tests/test_utils.py,sha256=eqdqbKNRWVMD
1350
1351
  vellum/workflows/nodes/displayable/bases/types.py,sha256=C37B2Qh2YP7s7pUjd-EYKc2Zl1TbnCgI_mENuUSb8bo,1706
1351
1352
  vellum/workflows/nodes/displayable/bases/utils.py,sha256=ckMUenSsNkiYmSw6FmjSMHYaCk8Y8_sUjL6lkFFEqts,5412
1352
1353
  vellum/workflows/nodes/displayable/code_execution_node/__init__.py,sha256=0FLWMMktpzSnmBMizQglBpcPrP80fzVsoJwJgf822Cg,76
1353
- vellum/workflows/nodes/displayable/code_execution_node/node.py,sha256=Hzc0h9sogX8DfFbJqdDLxGU2CMY1WvGosZ7taJC4sPE,8754
1354
+ vellum/workflows/nodes/displayable/code_execution_node/node.py,sha256=KZ5d3_mdpsrPF_ScmEqSfBhfup421RscO9hNiGa52T4,9068
1354
1355
  vellum/workflows/nodes/displayable/code_execution_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1355
1356
  vellum/workflows/nodes/displayable/code_execution_node/tests/fixtures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1356
1357
  vellum/workflows/nodes/displayable/code_execution_node/tests/fixtures/main.py,sha256=5QsbmkzSlSbcbWTG_JmIqcP-JNJzOPTKxGzdHos19W4,79
1357
- vellum/workflows/nodes/displayable/code_execution_node/tests/test_code_execution_node.py,sha256=s93M_EnU-4n60iSKv3FCf0kppwzFH5FNi9o9E58fQ3I,7510
1358
- vellum/workflows/nodes/displayable/code_execution_node/utils.py,sha256=LfI3kj2zQz6UGMld_uA9z2LjZobqRcgxQO4jdUWkg7o,376
1358
+ vellum/workflows/nodes/displayable/code_execution_node/tests/test_code_execution_node.py,sha256=ueVDw0GTSGzBZMFLs0NTir_0AE-pUrAYvpgg3Stex7Q,12350
1359
+ vellum/workflows/nodes/displayable/code_execution_node/utils.py,sha256=zRYM7B2t7355LzaAn6LkIn4tM5K7eQ0Kvje4NO6Kq30,3443
1359
1360
  vellum/workflows/nodes/displayable/conditional_node/__init__.py,sha256=AS_EIqFdU1F9t8aLmbZU-rLh9ry6LCJ0uj0D8F0L5Uw,72
1360
1361
  vellum/workflows/nodes/displayable/conditional_node/node.py,sha256=Qjfl33gZ3JEgxBA1EgzSUebboGvsARthIxxcQyvx5Gg,1152
1361
1362
  vellum/workflows/nodes/displayable/final_output_node/__init__.py,sha256=G7VXM4OWpubvSJtVkGmMNeqgb9GkM7qZT838eL18XU4,72
@@ -1386,7 +1387,7 @@ vellum/workflows/nodes/experimental/README.md,sha256=eF6DfIL8t-HbF9-mcofOMymKrra
1386
1387
  vellum/workflows/nodes/experimental/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1387
1388
  vellum/workflows/nodes/experimental/openai_chat_completion_node/__init__.py,sha256=lsyD9laR9p7kx5-BXGH2gUTM242UhKy8SMV0SR6S2iE,90
1388
1389
  vellum/workflows/nodes/experimental/openai_chat_completion_node/node.py,sha256=1EGeiaT-Zoo6pttQFKKBcdf3dmhAbjKGaErYD5FFwlc,10185
1389
- vellum/workflows/nodes/utils.py,sha256=tjBsootwm7vUq9qU4ttDL3CWH0C9Sd6QlX7IhfCCy34,2512
1390
+ vellum/workflows/nodes/utils.py,sha256=T7krLipDSI007JkkH2zsfyQ-tfOBH4hyFzQ0YJKYpuw,4025
1390
1391
  vellum/workflows/outputs/__init__.py,sha256=AyZ4pRh_ACQIGvkf0byJO46EDnSix1ZCAXfvh-ms1QE,94
1391
1392
  vellum/workflows/outputs/base.py,sha256=a7W6rNSDSawwGAXYjNTF2iHb9lnZu7WFSOagZIyy__k,7976
1392
1393
  vellum/workflows/ports/__init__.py,sha256=bZuMt-R7z5bKwpu4uPW7LlJeePOQWmCcDSXe5frUY5g,101
@@ -1397,7 +1398,7 @@ vellum/workflows/references/__init__.py,sha256=glHFC1VfXmcbNvH5VzFbkT03d8_D7MMcv
1397
1398
  vellum/workflows/references/constant.py,sha256=6yUT4q1sMj1hkI_tzzQ9AYcmeeDYFUNCqUq_W2DN0S8,540
1398
1399
  vellum/workflows/references/environment_variable.py,sha256=-gfOcdYwVp9ztSUYz6h2WI2Cg95zqxq5hhFf3Yr7aQg,791
1399
1400
  vellum/workflows/references/execution_count.py,sha256=JILHqt8ELdc9ct-WsVCA5X-rKiP1rmJODw-XTf4kpHI,722
1400
- vellum/workflows/references/external_input.py,sha256=XHugauKYvAmsGoFnjgJh00FcXjSMIqBvRun_CZuJD64,1662
1401
+ vellum/workflows/references/external_input.py,sha256=WyBC6uMDu77431YVSU_WvTt-nGLC_bW65tIsplUJXa4,2056
1401
1402
  vellum/workflows/references/input.py,sha256=3INu-TLTi4dziWmva6LO3WvgDlPzsjayUx61cVvqLJA,325
1402
1403
  vellum/workflows/references/lazy.py,sha256=SXwZUCTzUR-R2-uK0XHALtvp1x84l-QkNY-Ds6KynYA,1932
1403
1404
  vellum/workflows/references/node.py,sha256=LP854wDVs-9I_aZ7-nkbwXqL2H7W2_3LED2e9FixNS8,1418
@@ -1411,12 +1412,12 @@ vellum/workflows/runner/__init__.py,sha256=i1iG5sAhtpdsrlvwgH6B-m49JsINkiWyPWs8v
1411
1412
  vellum/workflows/runner/runner.py,sha256=LvP1UwLmwV1nCZYYrsiwtCzay73voMp1TDRVVBrlMj8,29196
1412
1413
  vellum/workflows/sandbox.py,sha256=GVJzVjMuYzOBnSrboB0_6MMRZWBluAyQ2o7syeaeBd0,2235
1413
1414
  vellum/workflows/state/__init__.py,sha256=yUUdR-_Vl7UiixNDYQZ-GEM_kJI9dnOia75TtuNEsnE,60
1414
- vellum/workflows/state/base.py,sha256=jpSzF1OQd3-fqi6dMGlNsQl-7JnJxCdzWIigmX8Wz-I,14425
1415
+ vellum/workflows/state/base.py,sha256=IIl76sJtn0GfbFWBqMnpGuvtZyVyQMEXv0QKDfLy8Wg,14763
1415
1416
  vellum/workflows/state/context.py,sha256=_NeGQpYo8yNuh0Tfh3OvcB_bG_-GC8b3ZLLl83Pf8-I,1279
1416
1417
  vellum/workflows/state/encoder.py,sha256=WdUidpOaBDx5lilJl8V8McFDHQYiCLCJR9dmktdzdZY,1836
1417
1418
  vellum/workflows/state/store.py,sha256=VYGBQgN1bpd1as5eGiouV_7scg8QsRs4_1aqZAGIsRQ,793
1418
1419
  vellum/workflows/state/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1419
- vellum/workflows/state/tests/test_state.py,sha256=7ap_Z9GJqyonZ1eVXwNyyuhV0AL5XiQ6uYCRhS7PFN4,3921
1420
+ vellum/workflows/state/tests/test_state.py,sha256=ucy7U8886J3CinIKQhOqv4dvkKWQk0fyK3JjTSiKZC4,5266
1420
1421
  vellum/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1421
1422
  vellum/workflows/tests/test_sandbox.py,sha256=JKwaluI-lODQo7Ek9sjDstjL_WTdSqUlVik6ZVTfVOA,1826
1422
1423
  vellum/workflows/types/__init__.py,sha256=KxUTMBGzuRCfiMqzzsykOeVvrrkaZmTTo1a7SLu8gRM,68
@@ -1441,8 +1442,8 @@ vellum/workflows/vellum_client.py,sha256=ODrq_TSl-drX2aezXegf7pizpWDVJuTXH-j6528
1441
1442
  vellum/workflows/workflows/__init__.py,sha256=KY45TqvavCCvXIkyCFMEc0dc6jTMOUci93U2DUrlZYc,66
1442
1443
  vellum/workflows/workflows/base.py,sha256=k0kUWWko4fHyCqLSU_1cBK_pXZpl9MXekWiG-bdOAo0,18353
1443
1444
  vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnadGsrSZGa7t7LpJA,2008
1444
- vellum_ai-0.13.14.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1445
- vellum_ai-0.13.14.dist-info/METADATA,sha256=-XRE0gS6VYSqoJt7wrYK1LcXz99LGaGwgY-9L7THqsg,5335
1446
- vellum_ai-0.13.14.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1447
- vellum_ai-0.13.14.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1448
- vellum_ai-0.13.14.dist-info/RECORD,,
1445
+ vellum_ai-0.13.18.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1446
+ vellum_ai-0.13.18.dist-info/METADATA,sha256=aLUy-xu3bfn69UAWushKWy3YWWoMMruLabea-UEOO1o,5335
1447
+ vellum_ai-0.13.18.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1448
+ vellum_ai-0.13.18.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1449
+ vellum_ai-0.13.18.dist-info/RECORD,,
vellum_cli/__init__.py CHANGED
@@ -56,6 +56,12 @@ def workflows():
56
56
 
57
57
  @workflows.command(name="push")
58
58
  @click.argument("module", required=False)
59
+ @click.option(
60
+ "--workflow-sandbox-id",
61
+ type=str,
62
+ help="""The specific Workflow Sandbox ID to use when pushing. Must either be already associated \
63
+ with the provided module or be available for use. The Workflow Sandbox must also exist in Vellum.""",
64
+ )
59
65
  @click.option("--deploy", is_flag=True, help="Deploy the Workflow after pushing it to Vellum")
60
66
  @click.option("--deployment-label", type=str, help="Label to use for the Deployment")
61
67
  @click.option("--deployment-name", type=str, help="Unique name for the Deployment")
@@ -74,6 +80,7 @@ def workflows():
74
80
  @click.option("--workspace", type=str, help="The specific Workspace config to use when pushing")
75
81
  def workflows_push(
76
82
  module: Optional[str],
83
+ workflow_sandbox_id: Optional[str],
77
84
  deploy: Optional[bool],
78
85
  deployment_label: Optional[str],
79
86
  deployment_name: Optional[str],
@@ -90,6 +97,7 @@ def workflows_push(
90
97
 
91
98
  push_command(
92
99
  module=module,
100
+ workflow_sandbox_id=workflow_sandbox_id,
93
101
  deploy=deploy,
94
102
  deployment_label=deployment_label,
95
103
  deployment_name=deployment_name,
@@ -103,6 +111,7 @@ def workflows_push(
103
111
 
104
112
  @push.command(name="*", hidden=True)
105
113
  @click.pass_context
114
+ @click.option("--workflow-sandbox-id", type=str, help="The specific Workflow Sandbox ID to use when pushing")
106
115
  @click.option("--deploy", is_flag=True, help="Deploy the Resource after pushing it to Vellum")
107
116
  @click.option("--deployment-label", type=str, help="Label to use for the Deployment")
108
117
  @click.option("--deployment-name", type=str, help="Unique name for the Deployment")
@@ -121,6 +130,7 @@ def workflows_push(
121
130
  @click.option("--workspace", type=str, help="The specific Workspace config to use when pushing")
122
131
  def push_module(
123
132
  ctx: click.Context,
133
+ workflow_sandbox_id: Optional[str],
124
134
  deploy: Optional[bool],
125
135
  deployment_label: Optional[str],
126
136
  deployment_name: Optional[str],
@@ -135,6 +145,7 @@ def push_module(
135
145
  if ctx.parent:
136
146
  push_command(
137
147
  module=ctx.parent.invoked_subcommand,
148
+ workflow_sandbox_id=workflow_sandbox_id,
138
149
  deploy=deploy,
139
150
  deployment_label=deployment_label,
140
151
  deployment_name=deployment_name,
vellum_cli/pull.py CHANGED
@@ -31,6 +31,16 @@ class WorkflowConfigResolutionResult(UniversalBaseModel):
31
31
  pk: Optional[str] = None
32
32
 
33
33
 
34
+ class RunnerConfig(UniversalBaseModel):
35
+ container_image_name: Optional[str] = None
36
+ container_image_tag: Optional[str] = None
37
+
38
+
39
+ class PullContentsMetadata(UniversalBaseModel):
40
+ label: Optional[str] = None
41
+ runner_config: Optional[RunnerConfig] = None
42
+
43
+
34
44
  def _resolve_workflow_config(
35
45
  config: VellumCliConfig,
36
46
  module: Optional[str] = None,
@@ -42,14 +52,33 @@ def _resolve_workflow_config(
42
52
 
43
53
  if module:
44
54
  workflow_config = next((w for w in config.workflows if w.module == module), None)
55
+ if not workflow_config and workflow_sandbox_id:
56
+ workflow_config = WorkflowConfig(
57
+ workflow_sandbox_id=workflow_sandbox_id,
58
+ module=module,
59
+ )
60
+ config.workflows.append(workflow_config)
61
+ return WorkflowConfigResolutionResult(
62
+ workflow_config=workflow_config,
63
+ pk=workflow_sandbox_id,
64
+ )
65
+
45
66
  return WorkflowConfigResolutionResult(
46
67
  workflow_config=workflow_config,
47
68
  pk=workflow_config.workflow_sandbox_id if workflow_config else None,
48
69
  )
49
70
  elif workflow_sandbox_id:
71
+ workflow_config = next((w for w in config.workflows if w.workflow_sandbox_id == workflow_sandbox_id), None)
72
+ if workflow_config:
73
+ return WorkflowConfigResolutionResult(
74
+ workflow_config=workflow_config,
75
+ pk=workflow_sandbox_id,
76
+ )
77
+
78
+ # We use an empty module name to indicate that we want to backfill it once we have the Workflow Sandbox Label
50
79
  workflow_config = WorkflowConfig(
51
80
  workflow_sandbox_id=workflow_sandbox_id,
52
- module=f"workflow_{workflow_sandbox_id.split('-')[0]}",
81
+ module="",
53
82
  )
54
83
  config.workflows.append(workflow_config)
55
84
  return WorkflowConfigResolutionResult(
@@ -98,7 +127,6 @@ def pull_command(
98
127
  workflow_sandbox_id=workflow_sandbox_id,
99
128
  workflow_deployment=workflow_deployment,
100
129
  )
101
- save_lock_file = not module
102
130
 
103
131
  workflow_config = workflow_config_result.workflow_config
104
132
  if not workflow_config:
@@ -108,7 +136,11 @@ def pull_command(
108
136
  if not pk:
109
137
  raise ValueError("No workflow sandbox ID found in project to pull from.")
110
138
 
111
- logger.info(f"Pulling workflow into {workflow_config.module}")
139
+ if workflow_config.module:
140
+ logger.info(f"Pulling workflow into {workflow_config.module}...")
141
+ else:
142
+ logger.info(f"Pulling workflow from {pk}...")
143
+
112
144
  client = create_vellum_client()
113
145
  query_parameters = {}
114
146
 
@@ -129,11 +161,30 @@ def pull_command(
129
161
  zip_bytes = b"".join(response)
130
162
  zip_buffer = io.BytesIO(zip_bytes)
131
163
 
132
- target_dir = os.path.join(os.getcwd(), *workflow_config.module.split("."))
133
164
  error_content = ""
134
- metadata_json: Optional[dict] = None
135
165
 
136
166
  with zipfile.ZipFile(zip_buffer) as zip_file:
167
+ if METADATA_FILE_NAME in zip_file.namelist():
168
+ metadata_json: Optional[dict] = None
169
+ with zip_file.open(METADATA_FILE_NAME) as source:
170
+ metadata_json = json.load(source)
171
+
172
+ pull_contents_metadata = PullContentsMetadata.model_validate(metadata_json)
173
+
174
+ if pull_contents_metadata.runner_config:
175
+ workflow_config.container_image_name = pull_contents_metadata.runner_config.container_image_name
176
+ workflow_config.container_image_tag = pull_contents_metadata.runner_config.container_image_tag
177
+ if workflow_config.container_image_name and not workflow_config.container_image_tag:
178
+ workflow_config.container_image_tag = "latest"
179
+
180
+ if not workflow_config.module and pull_contents_metadata.label:
181
+ workflow_config.module = snake_case(pull_contents_metadata.label)
182
+
183
+ if not workflow_config.module:
184
+ raise ValueError(f"Failed to resolve a module name for Workflow {pk}")
185
+
186
+ target_dir = os.path.join(os.getcwd(), *workflow_config.module.split("."))
187
+
137
188
  # Delete files in target_dir that aren't in the zip file
138
189
  if os.path.exists(target_dir):
139
190
  ignore_patterns = (
@@ -163,7 +214,6 @@ def pull_command(
163
214
  error_content = content
164
215
  continue
165
216
  if file_name == METADATA_FILE_NAME:
166
- metadata_json = json.loads(content)
167
217
  continue
168
218
 
169
219
  target_file = os.path.join(target_dir, file_name)
@@ -172,15 +222,6 @@ def pull_command(
172
222
  logger.info(f"Writing to {target_file}...")
173
223
  target.write(content)
174
224
 
175
- if metadata_json:
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"
183
-
184
225
  if include_json:
185
226
  logger.warning(
186
227
  """The pulled JSON representation of the Workflow should be used for debugging purposely only. \
@@ -190,16 +231,12 @@ Its schema should be considered unstable and subject to change at any time."""
190
231
  if include_sandbox:
191
232
  if not workflow_config.ignore:
192
233
  workflow_config.ignore = "sandbox.py"
193
- save_lock_file = True
194
234
  elif isinstance(workflow_config.ignore, str) and "sandbox.py" != workflow_config.ignore:
195
235
  workflow_config.ignore = [workflow_config.ignore, "sandbox.py"]
196
- save_lock_file = True
197
236
  elif isinstance(workflow_config.ignore, list) and "sandbox.py" not in workflow_config.ignore:
198
237
  workflow_config.ignore.append("sandbox.py")
199
- save_lock_file = True
200
238
 
201
- if save_lock_file:
202
- config.save()
239
+ config.save()
203
240
 
204
241
  if error_content:
205
242
  logger.error(error_content)
vellum_cli/push.py CHANGED
@@ -12,7 +12,6 @@ from dotenv import load_dotenv
12
12
  from vellum.client.core.api_error import ApiError
13
13
  from vellum.resources.workflows.client import OMIT
14
14
  from vellum.types import WorkflowPushDeploymentConfigRequest
15
- from vellum.workflows.utils.names import snake_to_title_case
16
15
  from vellum.workflows.vellum_client import create_vellum_client
17
16
  from vellum.workflows.workflows.base import BaseWorkflow
18
17
  from vellum_cli.config import DEFAULT_WORKSPACE_CONFIG, WorkflowConfig, WorkflowDeploymentConfig, load_vellum_cli_config
@@ -23,6 +22,7 @@ from vellum_ee.workflows.display.workflows.vellum_workflow_display import Vellum
23
22
 
24
23
  def push_command(
25
24
  module: Optional[str] = None,
25
+ workflow_sandbox_id: Optional[str] = None,
26
26
  deploy: Optional[bool] = None,
27
27
  deployment_label: Optional[str] = None,
28
28
  deployment_name: Optional[str] = None,
@@ -39,13 +39,24 @@ def push_command(
39
39
  if not config.workflows:
40
40
  raise ValueError("No Workflows found in project to push.")
41
41
 
42
- if len(config.workflows) > 1 and not module:
43
- raise ValueError("Multiple workflows found in project to push. Pushing only a single workflow is supported.")
42
+ workflow_configs = (
43
+ [
44
+ w
45
+ for w in config.workflows
46
+ if (module and w.module == module) or (workflow_sandbox_id and w.workflow_sandbox_id == workflow_sandbox_id)
47
+ ]
48
+ if module or workflow_sandbox_id
49
+ else config.workflows
50
+ )
44
51
 
45
- workflow_config = next((w for w in config.workflows if w.module == module), None) if module else config.workflows[0]
46
- if workflow_config is None:
52
+ if len(workflow_configs) == 0:
47
53
  raise ValueError(f"No workflow config for '{module}' found in project to push.")
48
54
 
55
+ if len(workflow_configs) > 1:
56
+ raise ValueError("Multiple workflows found in project to push. Pushing only a single workflow is supported.")
57
+
58
+ workflow_config = workflow_configs[0]
59
+
49
60
  logger.info(f"Loading workflow from {workflow_config.module}")
50
61
  resolved_workspace = workspace or workflow_config.workspace or DEFAULT_WORKSPACE_CONFIG.name
51
62
  workspace_config = (
@@ -65,6 +76,15 @@ def push_command(
65
76
  )
66
77
  config.workflows.append(workflow_config)
67
78
 
79
+ if (
80
+ workflow_sandbox_id
81
+ and workflow_config.workflow_sandbox_id
82
+ and workflow_config.workflow_sandbox_id != workflow_sandbox_id
83
+ ):
84
+ raise ValueError(
85
+ f"Workflow sandbox id '{workflow_sandbox_id}' is already associated with '{workflow_config.module}'."
86
+ )
87
+
68
88
  client = create_vellum_client(
69
89
  api_key=api_key,
70
90
  )
@@ -90,8 +110,6 @@ def push_command(
90
110
  "container_image_name": workflow_config.container_image_name,
91
111
  }
92
112
 
93
- label = snake_to_title_case(workflow_config.module.split(".")[-1])
94
-
95
113
  deployment_config: WorkflowPushDeploymentConfigRequest = OMIT
96
114
  deployment_config_serialized: str = OMIT
97
115
  if deploy:
@@ -137,8 +155,7 @@ def push_command(
137
155
  # Remove this once we could serialize using the artifact in Vembda
138
156
  # https://app.shortcut.com/vellum/story/5585
139
157
  exec_config=json.dumps(exec_config),
140
- label=label,
141
- workflow_sandbox_id=workflow_config.workflow_sandbox_id,
158
+ workflow_sandbox_id=workflow_config.workflow_sandbox_id or workflow_sandbox_id,
142
159
  artifact=artifact,
143
160
  # We should check with fern if we could auto-serialize typed object fields for us
144
161
  # https://app.shortcut.com/vellum/story/5568
@@ -209,7 +226,7 @@ def push_command(
209
226
  ) # type: ignore[attr-defined]
210
227
  else:
211
228
  logger.info(
212
- f"""Successfully pushed {label} to Vellum!
229
+ f"""Successfully pushed {workflow_config.module} to Vellum!
213
230
  Visit at: https://app.vellum.ai/workflow-sandboxes/{response.workflow_sandbox_id}"""
214
231
  )
215
232