vellum-ai 0.13.10__py3-none-any.whl → 0.13.11__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 (32) hide show
  1. vellum/client/core/client_wrapper.py +1 -1
  2. vellum/workflows/errors/types.py +21 -0
  3. vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py +14 -1
  4. vellum/workflows/nodes/displayable/bases/tests/test_utils.py +18 -0
  5. vellum/workflows/nodes/displayable/bases/utils.py +8 -1
  6. vellum/workflows/nodes/displayable/inline_prompt_node/tests/test_node.py +55 -0
  7. {vellum_ai-0.13.10.dist-info → vellum_ai-0.13.11.dist-info}/METADATA +1 -1
  8. {vellum_ai-0.13.10.dist-info → vellum_ai-0.13.11.dist-info}/RECORD +31 -31
  9. vellum_cli/__init__.py +9 -1
  10. vellum_cli/config.py +29 -1
  11. vellum_cli/push.py +24 -3
  12. vellum_cli/tests/conftest.py +3 -0
  13. vellum_cli/tests/test_pull.py +6 -0
  14. vellum_cli/tests/test_push.py +88 -1
  15. vellum_ee/workflows/display/nodes/base_node_display.py +110 -6
  16. vellum_ee/workflows/display/nodes/base_node_vellum_display.py +16 -1
  17. vellum_ee/workflows/display/nodes/get_node_display_class.py +6 -4
  18. vellum_ee/workflows/display/nodes/vellum/__init__.py +0 -2
  19. vellum_ee/workflows/display/nodes/vellum/error_node.py +9 -3
  20. vellum_ee/workflows/display/nodes/vellum/tests/test_error_node.py +44 -0
  21. vellum_ee/workflows/display/nodes/vellum/try_node.py +3 -4
  22. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py +1 -1
  23. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +5 -2
  24. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +1 -1
  25. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py +1 -1
  26. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py +1 -1
  27. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py +15 -1
  28. vellum_ee/workflows/display/workflows/vellum_workflow_display.py +27 -13
  29. vellum_ee/workflows/display/nodes/vellum/base_node.py +0 -121
  30. {vellum_ai-0.13.10.dist-info → vellum_ai-0.13.11.dist-info}/LICENSE +0 -0
  31. {vellum_ai-0.13.10.dist-info → vellum_ai-0.13.11.dist-info}/WHEEL +0 -0
  32. {vellum_ai-0.13.10.dist-info → vellum_ai-0.13.11.dist-info}/entry_points.txt +0 -0
@@ -18,7 +18,7 @@ class BaseClientWrapper:
18
18
  headers: typing.Dict[str, str] = {
19
19
  "X-Fern-Language": "Python",
20
20
  "X-Fern-SDK-Name": "vellum-ai",
21
- "X-Fern-SDK-Version": "0.13.10",
21
+ "X-Fern-SDK-Version": "0.13.11",
22
22
  }
23
23
  headers["X_API_KEY"] = self.api_key
24
24
  return headers
@@ -61,3 +61,24 @@ def workflow_event_error_to_workflow_error(error: WorkflowEventError) -> Workflo
61
61
  message=error.message,
62
62
  code=_WORKFLOW_EVENT_ERROR_CODE_TO_WORKFLOW_ERROR_CODE.get(error.code, WorkflowErrorCode.INTERNAL_ERROR),
63
63
  )
64
+
65
+
66
+ _WORKFLOW_ERROR_CODE_TO_VELLUM_ERROR_CODE: Dict[WorkflowErrorCode, VellumErrorCodeEnum] = {
67
+ WorkflowErrorCode.INVALID_WORKFLOW: "INVALID_REQUEST",
68
+ WorkflowErrorCode.INVALID_INPUTS: "INVALID_INPUTS",
69
+ WorkflowErrorCode.INVALID_OUTPUTS: "INVALID_REQUEST",
70
+ WorkflowErrorCode.INVALID_STATE: "INVALID_REQUEST",
71
+ WorkflowErrorCode.INVALID_TEMPLATE: "INVALID_INPUTS",
72
+ WorkflowErrorCode.INTERNAL_ERROR: "INTERNAL_SERVER_ERROR",
73
+ WorkflowErrorCode.NODE_EXECUTION: "USER_DEFINED_ERROR",
74
+ WorkflowErrorCode.PROVIDER_ERROR: "PROVIDER_ERROR",
75
+ WorkflowErrorCode.USER_DEFINED_ERROR: "USER_DEFINED_ERROR",
76
+ WorkflowErrorCode.WORKFLOW_CANCELLED: "REQUEST_TIMEOUT",
77
+ }
78
+
79
+
80
+ def workflow_error_to_vellum_error(error: WorkflowError) -> VellumError:
81
+ return VellumError(
82
+ message=error.message,
83
+ code=_WORKFLOW_ERROR_CODE_TO_VELLUM_ERROR_CODE.get(error.code, "INTERNAL_SERVER_ERROR"),
84
+ )
@@ -2,6 +2,7 @@ from abc import abstractmethod
2
2
  from typing import ClassVar, Generator, Generic, Iterator, List, Optional, Union
3
3
 
4
4
  from vellum import AdHocExecutePromptEvent, ExecutePromptEvent, PromptOutput
5
+ from vellum.client.core.api_error import ApiError
5
6
  from vellum.core import RequestOptions
6
7
  from vellum.workflows.errors.types import WorkflowErrorCode, vellum_error_to_workflow_error
7
8
  from vellum.workflows.exceptions import NodeException
@@ -36,7 +37,19 @@ class BasePromptNode(BaseNode, Generic[StateType]):
36
37
  )
37
38
 
38
39
  def _process_prompt_event_stream(self) -> Generator[BaseOutput, None, Optional[List[PromptOutput]]]:
39
- prompt_event_stream = self._get_prompt_event_stream()
40
+ try:
41
+ prompt_event_stream = self._get_prompt_event_stream()
42
+ except ApiError as e:
43
+ if e.status_code and e.status_code >= 400 and e.status_code < 500 and isinstance(e.body, dict):
44
+ raise NodeException(
45
+ message=e.body.get("detail", "Failed to execute prompt"),
46
+ code=WorkflowErrorCode.INVALID_INPUTS,
47
+ ) from e
48
+
49
+ raise NodeException(
50
+ message="Failed to execute prompt",
51
+ code=WorkflowErrorCode.INTERNAL_ERROR,
52
+ ) from e
40
53
 
41
54
  outputs: Optional[List[PromptOutput]] = None
42
55
  for event in prompt_event_stream:
@@ -1,8 +1,11 @@
1
1
  import pytest
2
2
  import enum
3
3
 
4
+ from pydantic import BaseModel
5
+
4
6
  from vellum.client.types.chat_history_vellum_value import ChatHistoryVellumValue
5
7
  from vellum.client.types.chat_message import ChatMessage
8
+ from vellum.client.types.error_vellum_value import ErrorVellumValue
6
9
  from vellum.client.types.json_vellum_value import JsonVellumValue
7
10
  from vellum.client.types.number_vellum_value import NumberVellumValue
8
11
  from vellum.client.types.search_result import SearchResult
@@ -10,6 +13,8 @@ from vellum.client.types.search_result_document import SearchResultDocument
10
13
  from vellum.client.types.search_results_vellum_value import SearchResultsVellumValue
11
14
  from vellum.client.types.string_vellum_value import StringVellumValue
12
15
  from vellum.client.types.string_vellum_value_request import StringVellumValueRequest
16
+ from vellum.client.types.vellum_error import VellumError
17
+ from vellum.workflows.errors.types import WorkflowError, WorkflowErrorCode
13
18
  from vellum.workflows.nodes.displayable.bases.utils import primitive_to_vellum_value, primitive_to_vellum_value_request
14
19
 
15
20
 
@@ -17,6 +22,10 @@ class MockEnum(enum.Enum):
17
22
  FOO = "foo"
18
23
 
19
24
 
25
+ class RandomPydanticModel(BaseModel):
26
+ foo: str
27
+
28
+
20
29
  @pytest.mark.parametrize(
21
30
  ["value", "expected_output"],
22
31
  [
@@ -51,6 +60,15 @@ class MockEnum(enum.Enum):
51
60
  (StringVellumValue(value="hello"), StringVellumValue(value="hello")),
52
61
  (StringVellumValueRequest(value="hello"), StringVellumValueRequest(value="hello")),
53
62
  ({"foo": "bar"}, JsonVellumValue(value={"foo": "bar"})),
63
+ (
64
+ VellumError(message="hello", code="USER_DEFINED_ERROR"),
65
+ ErrorVellumValue(value=VellumError(message="hello", code="USER_DEFINED_ERROR")),
66
+ ),
67
+ (
68
+ WorkflowError(message="hello", code=WorkflowErrorCode.USER_DEFINED_ERROR),
69
+ ErrorVellumValue(value=VellumError(message="hello", code="USER_DEFINED_ERROR")),
70
+ ),
71
+ (RandomPydanticModel(foo="bar"), JsonVellumValue(value={"foo": "bar"})),
54
72
  ],
55
73
  )
56
74
  def test_primitive_to_vellum_value(value, expected_output):
@@ -25,8 +25,11 @@ from vellum.client.types.search_results_vellum_value import SearchResultsVellumV
25
25
  from vellum.client.types.search_results_vellum_value_request import SearchResultsVellumValueRequest
26
26
  from vellum.client.types.string_vellum_value import StringVellumValue
27
27
  from vellum.client.types.string_vellum_value_request import StringVellumValueRequest
28
+ from vellum.client.types.vellum_error import VellumError
28
29
  from vellum.client.types.vellum_value import VellumValue
29
30
  from vellum.client.types.vellum_value_request import VellumValueRequest
31
+ from vellum.workflows.errors.types import WorkflowError, workflow_error_to_vellum_error
32
+ from vellum.workflows.state.encoder import DefaultStateEncoder
30
33
 
31
34
  VELLUM_VALUE_REQUEST_TUPLE = (
32
35
  StringVellumValueRequest,
@@ -63,6 +66,10 @@ def primitive_to_vellum_value(value: Any) -> VellumValue:
63
66
  ):
64
67
  search_results = cast(Union[List[SearchResultRequest], List[SearchResult]], value)
65
68
  return SearchResultsVellumValue(value=search_results)
69
+ elif isinstance(value, VellumError):
70
+ return ErrorVellumValue(value=value)
71
+ elif isinstance(value, WorkflowError):
72
+ return ErrorVellumValue(value=workflow_error_to_vellum_error(value))
66
73
  elif isinstance(
67
74
  value,
68
75
  (
@@ -88,7 +95,7 @@ def primitive_to_vellum_value(value: Any) -> VellumValue:
88
95
  return value # type: ignore
89
96
 
90
97
  try:
91
- json_value = json.dumps(value)
98
+ json_value = json.dumps(value, cls=DefaultStateEncoder)
92
99
  except json.JSONDecodeError:
93
100
  raise ValueError(f"Unsupported variable type: {value.__class__.__name__}")
94
101
 
@@ -1,7 +1,9 @@
1
+ import pytest
1
2
  from dataclasses import dataclass
2
3
  from uuid import uuid4
3
4
  from typing import Any, Iterator, List
4
5
 
6
+ from vellum.client.core.api_error import ApiError
5
7
  from vellum.client.core.pydantic_utilities import UniversalBaseModel
6
8
  from vellum.client.types.execute_prompt_event import ExecutePromptEvent
7
9
  from vellum.client.types.fulfilled_execute_prompt_event import FulfilledExecutePromptEvent
@@ -12,6 +14,8 @@ from vellum.client.types.initiated_execute_prompt_event import InitiatedExecuteP
12
14
  from vellum.client.types.prompt_output import PromptOutput
13
15
  from vellum.client.types.prompt_request_json_input import PromptRequestJsonInput
14
16
  from vellum.client.types.string_vellum_value import StringVellumValue
17
+ from vellum.workflows.errors.types import WorkflowErrorCode
18
+ from vellum.workflows.exceptions import NodeException
15
19
  from vellum.workflows.nodes.displayable.inline_prompt_node.node import InlinePromptNode
16
20
 
17
21
 
@@ -126,3 +130,54 @@ def test_inline_prompt_node__function_definitions(vellum_adhoc_prompt_client):
126
130
  "name": "my_function"
127
131
  }"""
128
132
  )
133
+
134
+
135
+ @pytest.mark.parametrize(
136
+ ["exception", "expected_code", "expected_message"],
137
+ [
138
+ (
139
+ ApiError(status_code=404, body={"detail": "Model not found"}),
140
+ WorkflowErrorCode.INVALID_INPUTS,
141
+ "Model not found",
142
+ ),
143
+ (
144
+ ApiError(status_code=404, body={"message": "Model not found"}),
145
+ WorkflowErrorCode.INVALID_INPUTS,
146
+ "Failed to execute prompt",
147
+ ),
148
+ (
149
+ ApiError(status_code=404, body="Model not found"),
150
+ WorkflowErrorCode.INTERNAL_ERROR,
151
+ "Failed to execute prompt",
152
+ ),
153
+ (
154
+ ApiError(status_code=None, body={"detail": "Model not found"}),
155
+ WorkflowErrorCode.INTERNAL_ERROR,
156
+ "Failed to execute prompt",
157
+ ),
158
+ (
159
+ ApiError(status_code=500, body={"detail": "Model not found"}),
160
+ WorkflowErrorCode.INTERNAL_ERROR,
161
+ "Failed to execute prompt",
162
+ ),
163
+ ],
164
+ ids=["404", "invalid_dict", "invalid_body", "no_status_code", "500"],
165
+ )
166
+ def test_inline_prompt_node__api_error__invalid_inputs_node_exception(
167
+ vellum_adhoc_prompt_client, exception, expected_code, expected_message
168
+ ):
169
+ # GIVEN a prompt node with an invalid model name
170
+ class MyNode(InlinePromptNode):
171
+ ml_model = "my-invalid-model"
172
+ blocks = []
173
+
174
+ # AND the adhoc prompt client raises a 4xx error
175
+ vellum_adhoc_prompt_client.adhoc_execute_prompt_stream.side_effect = exception
176
+
177
+ # WHEN the node is run
178
+ with pytest.raises(NodeException) as e:
179
+ list(MyNode().run())
180
+
181
+ # THEN the node raises the correct NodeException
182
+ assert e.value.code == expected_code
183
+ assert e.value.message == expected_message
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vellum-ai
3
- Version: 0.13.10
3
+ Version: 0.13.11
4
4
  Summary:
5
5
  License: MIT
6
6
  Requires-Python: >=3.9,<4.0
@@ -1,39 +1,38 @@
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=L8D7nVwC63WdAe6HTy7J_S3wCvjJBHDWaBkCrw76dtU,9573
3
+ vellum_cli/__init__.py,sha256=tRcOi6oLzT3EXORlHwGzo0Sn1-npf8Jf7mMi90NDUh0,10035
4
4
  vellum_cli/aliased_group.py,sha256=ugW498j0yv4ALJ8vS9MsO7ctDW7Jlir9j6nE_uHAP8c,3363
5
- vellum_cli/config.py,sha256=998IZbvkrw2avjbvs8bw6NrbEgGz5UBKRbvKAcastJg,5493
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
9
  vellum_cli/pull.py,sha256=zf0y22XptUYI_hMP_4Q1CEo9s2wALsTJcCXNd-_ibd8,7551
10
- vellum_cli/push.py,sha256=KHakWiUwdeZff8QZSDF0l8xmCgMRo9ntan8kaLD02Lc,7677
10
+ vellum_cli/push.py,sha256=0Q3Of25KzqDq0KTgkXQ22nAhSH4_JI424hKwKkj3RWs,8627
11
11
  vellum_cli/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
- vellum_cli/tests/conftest.py,sha256=Jv-QUjXoCDhsvVvXEjOenNqRArO_xXhtNuCYt4wiOyE,1421
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=6gbASF6ASy5YcdWjOCt6b5K0u2VWsFegdrTWu6sEVKs,19613
17
- vellum_cli/tests/test_push.py,sha256=PVxKwbWHjb1QwQ0n4tTqh2Tj6yg2cOGupOSXaXl08DI,11044
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
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=aucM0ta33owcDwxP-zOvCm9Nb7q7wzjDfxrnyKPV5W4,11423
25
- vellum_ee/workflows/display/nodes/base_node_vellum_display.py,sha256=BxA-YVUJvB36NM-Q5DNCwckeqymwLKMp9DVCaTyrPbs,2253
26
- vellum_ee/workflows/display/nodes/get_node_display_class.py,sha256=vyKeJAevAXvEAEtWeTEdBZXD3eJQYW_DEXLKVZ5KmYc,1325
24
+ vellum_ee/workflows/display/nodes/base_node_display.py,sha256=AnACr-QfL4Hwc3JEN9tUDmr0c8DE9uAjP8w7NyXAfj4,15413
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
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=_raKY9eKi_OvIFn6nGvf9xKSboKtYLHCWaWCwDQFbOc,1567
31
+ vellum_ee/workflows/display/nodes/vellum/__init__.py,sha256=nmPLj8vkbVCS46XQqmHq8Xj8Mr36wCK_vWf26A9KIkw,1505
32
32
  vellum_ee/workflows/display/nodes/vellum/api_node.py,sha256=hoV-cUtS6H9kmRQXHd2py95GRWI_dAnnaPwvlNBkDOQ,8571
33
- vellum_ee/workflows/display/nodes/vellum/base_node.py,sha256=BE5bn7_SQ23r2jWEFVJcS6fZzB5fXX9uaADya9NIE6Y,4799
34
33
  vellum_ee/workflows/display/nodes/vellum/code_execution_node.py,sha256=z00Z3L0d4PsUQo4S8FRDTtOFLtjdi17TJbatNVF4nM8,4288
35
34
  vellum_ee/workflows/display/nodes/vellum/conditional_node.py,sha256=ybLIa4uclqVIy3VAQvI1ivg2tnK5Ug_1R5a69DFqL7E,11104
36
- vellum_ee/workflows/display/nodes/vellum/error_node.py,sha256=Tyx74dUmj_ef0slptoUXHtkjLbNd3f4hXeoEozFaFcw,2023
35
+ vellum_ee/workflows/display/nodes/vellum/error_node.py,sha256=I1Jkp2htRINJATtv1e-zs9BrReFX842djpiVgBPHDYg,2186
37
36
  vellum_ee/workflows/display/nodes/vellum/final_output_node.py,sha256=p-PvlnxpBQ7IKskZi2A19jKAtKnSxJ8LPbGMA83VkFk,2805
38
37
  vellum_ee/workflows/display/nodes/vellum/guardrail_node.py,sha256=aYZSJTxknU4LMiQdWk9LcK6CkhdozeDEMiRxfAyUNEc,2202
39
38
  vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py,sha256=h8K183cZsU2b86WYQlqFtwMkwIHydnNr4ZaaQcWnFWo,7316
@@ -46,24 +45,25 @@ vellum_ee/workflows/display/nodes/vellum/search_node.py,sha256=TxcAGZDl_hvJ7Y1hU
46
45
  vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py,sha256=lfevlHpGEX14dEDym6qmnkw3nvzQPTB1_D2ch12B_Rk,2701
47
46
  vellum_ee/workflows/display/nodes/vellum/templating_node.py,sha256=JVIMPR3WpveOCWZubHKZkE04mavnTdb_9QY_r3XliRg,3424
48
47
  vellum_ee/workflows/display/nodes/vellum/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
48
+ vellum_ee/workflows/display/nodes/vellum/tests/test_error_node.py,sha256=ulrpoYUW-5kIxfG4Lf5F2p0k_EoYKhmahEbF3P_eruM,1648
49
49
  vellum_ee/workflows/display/nodes/vellum/tests/test_try_node.py,sha256=mtzB8LJlFCHVFM4H5AanLp29gQfaVmnN4A4iaRGJHoI,2427
50
50
  vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py,sha256=3uT7Gbc0f_mQ3u8uZuCWd0mJ4GtWbz2gbUMySYaVlNE,3774
51
- vellum_ee/workflows/display/nodes/vellum/try_node.py,sha256=tkKILq38n3QXcd2A-RfW8DeHas0I3MII3mexIYYKMtg,5985
51
+ vellum_ee/workflows/display/nodes/vellum/try_node.py,sha256=EoU1J7HfcszAZr7ROy_xsNhaDBRiI95-wTK-OzgBwvg,5861
52
52
  vellum_ee/workflows/display/nodes/vellum/utils.py,sha256=aBmTg9pJloG1BxhYcqzxs5JOA-IixncLVr1XiDzANnA,4313
53
53
  vellum_ee/workflows/display/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
54
  vellum_ee/workflows/display/tests/test_vellum_workflow_display.py,sha256=h4bE187MyM0eT_elFnOxwsCeMHeuzSK0orjgAy8kV1k,4952
55
55
  vellum_ee/workflows/display/tests/workflow_serialization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
56
56
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py,sha256=g4R4vnZDcpeZ7jCGpqZhDx8z7Kt1dH7r9iDfCLKJ56A,2252
58
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py,sha256=jCvt_plgTaKlf5H7alWhYHihvc-Y4p635UhHCjQSbmM,7115
59
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py,sha256=hcsK36oU9UvYNOdhdKnn2nO36IPzqM4XOxLcz6od9mE,10228
60
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py,sha256=kuJek64zXtrQZPcSFENr12EST_zaypPzFh67xIr6PXU,6260
61
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py,sha256=7BRX1Qz1VF_eMqazp6FhlYcOK6sj8p-qu43l7SI4JF0,37351
57
+ 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_attributes_serialization.py,sha256=9CV44pY33cL_RF9cKmNVwn5hDGEZbPIETavOrvIL3oY,10229
60
+ vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py,sha256=-12ZkZb3f5gyoNASV2yeQtMo5HmNsVEo8nXwL6IC-I8,6261
61
+ vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py,sha256=6th6kCwzql6lddjkTQx4Jbvvs4ChqtJwctW-B4QuBhI,37352
62
62
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py,sha256=EbVgg_3_ipTt3MOop4RARX0fmNjwqZtkhIXzx9nGw7Y,4487
63
63
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py,sha256=bXZWxOKAVjZlbP3iLHPHGA4aPs0EguKlQqmYPNGv3cU,16391
64
64
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py,sha256=uvABhpstyxNNOz50-XJMAr3SKp8gluPp1mUtJjvRL0c,29410
65
65
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py,sha256=n3F_Eyru0DYOszBH4jplz7Mzt2FfBNxGlCkTFqvrX-M,48399
66
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py,sha256=QVlkczxzaKuOhwbRvVP70otPDNnJcSGDfN79j92lFyk,5534
66
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py,sha256=8LhQgW0uzVOhzz0AwdM-EYugVO-0mGWglxWo_lON4D8,6079
67
67
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py,sha256=yWDykoHUjuiVYdevcJxWmYDDmbIszpHKYBu19vqR-I8,5746
68
68
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py,sha256=mEkvKUrt8U6e9bN65QRG7Zd3KdCdoMvHm96LjGwy96k,7427
69
69
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py,sha256=CxbnZ3tB8gir9xopixjvT0hNYyjMHvT_m8BzY5kl8Dg,21497
@@ -83,7 +83,7 @@ vellum_ee/workflows/display/vellum.py,sha256=8xXRI8b8Tt661H-iZreTQTvLNEKUr4lf-Xa
83
83
  vellum_ee/workflows/display/workflows/__init__.py,sha256=kapXsC67VJcgSuiBMa86FdePG5A9kMB5Pi4Uy1O2ob4,207
84
84
  vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256=x4C621UTH_SZLJYmVBiC1q-D-wadJlTiSGlKAI6CUbA,14082
85
85
  vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py,sha256=kp0u8LN_2IwshLrhMImhpZx1hRyAcD5gXY-kDuuaGMQ,1269
86
- vellum_ee/workflows/display/workflows/vellum_workflow_display.py,sha256=ReEaGb0IBWYeTmEvP5ObcJlTe6RtAogOZlemHkEwBcM,16486
86
+ vellum_ee/workflows/display/workflows/vellum_workflow_display.py,sha256=wij6U6-20QSDlfLMCeHjmpkWWuSA8fWYWJV17dw6L98,17187
87
87
  vellum_ee/workflows/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
88
88
  vellum_ee/workflows/server/virtual_file_loader.py,sha256=X_DdNK7MfyOjKWekk6YQpOSCT6klKcdjT6nVJcBH1sM,1481
89
89
  vellum_ee/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -112,7 +112,7 @@ vellum/client/README.md,sha256=JkCJjmMZl4jrPj46pkmL9dpK4gSzQQmP5I7z4aME4LY,4749
112
112
  vellum/client/__init__.py,sha256=8nZt88C9SVwWanjLbIQMU3rzb32h5UZfFMBx3VPHB50,111887
113
113
  vellum/client/core/__init__.py,sha256=SQ85PF84B9MuKnBwHNHWemSGuy-g_515gFYNFhvEE0I,1438
114
114
  vellum/client/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
115
- vellum/client/core/client_wrapper.py,sha256=QFtPX3r8rOjA_HWWWzqeN6YXR94sGx14HQGv7kmubTA,1869
115
+ vellum/client/core/client_wrapper.py,sha256=WdGHbGL6B-WAReI6C1XsH60HY57mtWSg-jZ-2xz4eiQ,1869
116
116
  vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
117
117
  vellum/client/core/file.py,sha256=X9IbmkZmB2bB_DpmZAO3crWdXagOakAyn6UCOCImCPg,2322
118
118
  vellum/client/core/http_client.py,sha256=R0pQpCppnEtxccGvXl4uJ76s7ro_65Fo_erlNNLp_AI,19228
@@ -1260,7 +1260,7 @@ vellum/workflows/emitters/base.py,sha256=D5SADKIvnbgKwIBgYm77jaqvpo1o0rz4MmuX_mu
1260
1260
  vellum/workflows/environment/__init__.py,sha256=wGHslgSEZ7Octe4C-hNtl84EFelNimgmWQoi7px4-uw,71
1261
1261
  vellum/workflows/environment/environment.py,sha256=IwcVSwA51jW1JTN_MAN22UbeAtZhiAVa_JRV4rmpAAs,219
1262
1262
  vellum/workflows/errors/__init__.py,sha256=tWGPu5xyAU8gRb8_bl0fL7OfU3wxQ9UH6qVwy4X4P_Q,113
1263
- vellum/workflows/errors/types.py,sha256=mvywC2sXtpRrkDRfTx-O6aXAp0hOFyx27a1tqguKt4g,2493
1263
+ vellum/workflows/errors/types.py,sha256=-Ls41oM4HN28b78Ou13FoZnaWRuaxBgTarKgSoBlCKc,3413
1264
1264
  vellum/workflows/events/__init__.py,sha256=6pxxceJo2dcaRkWtkDAYlUQZ-PHBQSZytIoyuUK48Qw,759
1265
1265
  vellum/workflows/events/node.py,sha256=uHT6If0esgZ3nLjrjmUPTKf3qbjGhoV_x5YKpjDBDcU,5280
1266
1266
  vellum/workflows/events/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -1339,16 +1339,16 @@ vellum/workflows/nodes/displayable/bases/__init__.py,sha256=0mWIx3qUrzllV7jqt7wN
1339
1339
  vellum/workflows/nodes/displayable/bases/api_node/__init__.py,sha256=1jwx4WC358CLA1jgzl_UD-rZmdMm2v9Mps39ndwCD7U,64
1340
1340
  vellum/workflows/nodes/displayable/bases/api_node/node.py,sha256=kKiwrz8XGJkvFjipBthxs9h1e2ndWPgmpEzZiYs0I5I,2579
1341
1341
  vellum/workflows/nodes/displayable/bases/base_prompt_node/__init__.py,sha256=Org3xTvgp1pA0uUXFfnJr29D3HzCey2lEdYF4zbIUgo,70
1342
- vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py,sha256=reDW1aHetmkesyq9iVrbTtesql-SFUsd2LygGLfdJPo,2258
1342
+ vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py,sha256=r_gOmeGFQQfzhAc1_bmzcwUvH-Xllc93gE7miTV4rQE,2824
1343
1343
  vellum/workflows/nodes/displayable/bases/inline_prompt_node/__init__.py,sha256=Hl35IAoepRpE-j4cALaXVJIYTYOF3qszyVbxTj4kS1s,82
1344
1344
  vellum/workflows/nodes/displayable/bases/inline_prompt_node/constants.py,sha256=fnjiRWLoRlC4Puo5oQcpZD5Hd-EesxsAo9l5tGAkpZQ,270
1345
1345
  vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py,sha256=j6AKAVIl_uU77a6JMGnMTyFnnK-jsfPVthxrgbltQRE,6453
1346
1346
  vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py,sha256=FAY6cR3rlIWsufprA6WXefOaU2J1LK0HFfQkBxCQ-yI,5181
1347
1347
  vellum/workflows/nodes/displayable/bases/search_node.py,sha256=3UtbqY3QO4kzfJHbmUNZGnEEfJmaoiF892u8H6TGjp8,5381
1348
1348
  vellum/workflows/nodes/displayable/bases/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1349
- vellum/workflows/nodes/displayable/bases/tests/test_utils.py,sha256=uQM9RTVmC-fMQ4hd4481QZbviokshwYSxk1ee9leh3A,2406
1349
+ vellum/workflows/nodes/displayable/bases/tests/test_utils.py,sha256=eqdqbKNRWVMDPevgwLg1i6YK0g4L4bCy-7xCBN5yYZI,3156
1350
1350
  vellum/workflows/nodes/displayable/bases/types.py,sha256=C37B2Qh2YP7s7pUjd-EYKc2Zl1TbnCgI_mENuUSb8bo,1706
1351
- vellum/workflows/nodes/displayable/bases/utils.py,sha256=hlbIRLAAeqRhzZPLK7WDvBzUT2b6tupaXYOF54iYvS0,4973
1351
+ vellum/workflows/nodes/displayable/bases/utils.py,sha256=ckMUenSsNkiYmSw6FmjSMHYaCk8Y8_sUjL6lkFFEqts,5412
1352
1352
  vellum/workflows/nodes/displayable/code_execution_node/__init__.py,sha256=0FLWMMktpzSnmBMizQglBpcPrP80fzVsoJwJgf822Cg,76
1353
1353
  vellum/workflows/nodes/displayable/code_execution_node/node.py,sha256=Hzc0h9sogX8DfFbJqdDLxGU2CMY1WvGosZ7taJC4sPE,8754
1354
1354
  vellum/workflows/nodes/displayable/code_execution_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -1365,7 +1365,7 @@ vellum/workflows/nodes/displayable/guardrail_node/node.py,sha256=h5nIBzQxbXTrdTq
1365
1365
  vellum/workflows/nodes/displayable/inline_prompt_node/__init__.py,sha256=gSUOoEZLlrx35-tQhSAd3An8WDwBqyiQh-sIebLU9wU,74
1366
1366
  vellum/workflows/nodes/displayable/inline_prompt_node/node.py,sha256=UWOxIa3kizhDa5joAmEDlh0P66EaqatqxzLLbvbUybw,2294
1367
1367
  vellum/workflows/nodes/displayable/inline_prompt_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1368
- vellum/workflows/nodes/displayable/inline_prompt_node/tests/test_node.py,sha256=57JYbHvfZAjEGfa4CvYSpAt5yLDj0bPIr1_RoG8n9oI,4725
1368
+ vellum/workflows/nodes/displayable/inline_prompt_node/tests/test_node.py,sha256=BEKdts18soB6gaW_d3VbhDy7IFzFmC76j5lRYiTOj44,6643
1369
1369
  vellum/workflows/nodes/displayable/merge_node/__init__.py,sha256=J8IC08dSH7P76wKlNuxe1sn7toNGtSQdFirUbtPDEs0,60
1370
1370
  vellum/workflows/nodes/displayable/merge_node/node.py,sha256=nZtGGVAvY4fvGg8vwV6sTQ8_QLRnigeXt0vf2FL272A,450
1371
1371
  vellum/workflows/nodes/displayable/note_node/__init__.py,sha256=KWA3P4fyYJ-fOTky8qNGlcOotQ-HeHJ9AjZt6mRQmCE,58
@@ -1441,8 +1441,8 @@ vellum/workflows/vellum_client.py,sha256=ODrq_TSl-drX2aezXegf7pizpWDVJuTXH-j6528
1441
1441
  vellum/workflows/workflows/__init__.py,sha256=KY45TqvavCCvXIkyCFMEc0dc6jTMOUci93U2DUrlZYc,66
1442
1442
  vellum/workflows/workflows/base.py,sha256=k0kUWWko4fHyCqLSU_1cBK_pXZpl9MXekWiG-bdOAo0,18353
1443
1443
  vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnadGsrSZGa7t7LpJA,2008
1444
- vellum_ai-0.13.10.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1445
- vellum_ai-0.13.10.dist-info/METADATA,sha256=qsbrVIIP35E7Q0tVUt2vd_NXWi9dYkUcksWgKYnCPy8,5335
1446
- vellum_ai-0.13.10.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1447
- vellum_ai-0.13.10.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1448
- vellum_ai-0.13.10.dist-info/RECORD,,
1444
+ vellum_ai-0.13.11.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1445
+ vellum_ai-0.13.11.dist-info/METADATA,sha256=NHPCibqYzo79FZeV0pFNsUB0dbOubh76GZRnzEJAc74,5335
1446
+ vellum_ai-0.13.11.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1447
+ vellum_ai-0.13.11.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1448
+ vellum_ai-0.13.11.dist-info/RECORD,,
vellum_cli/__init__.py CHANGED
@@ -37,13 +37,15 @@ class PushGroup(ClickAliasedGroup):
37
37
 
38
38
  @main.group(invoke_without_command=True, cls=PushGroup)
39
39
  @click.pass_context
40
+ @click.option("--workspace", type=str, help="The specific Workspace config to use when pushing")
40
41
  def push(
41
42
  ctx: click.Context,
43
+ workspace: Optional[str],
42
44
  ) -> None:
43
45
  """Push Resources to Vellum"""
44
46
 
45
47
  if ctx.invoked_subcommand is None:
46
- push_command()
48
+ push_command(workspace=workspace)
47
49
 
48
50
 
49
51
  @main.group()
@@ -69,6 +71,7 @@ def workflows():
69
71
  is_flag=True,
70
72
  help="Raises an error if we detect an unexpected discrepancy in the generated artifact.",
71
73
  )
74
+ @click.option("--workspace", type=str, help="The specific Workspace config to use when pushing")
72
75
  def workflows_push(
73
76
  module: Optional[str],
74
77
  deploy: Optional[bool],
@@ -78,6 +81,7 @@ def workflows_push(
78
81
  release_tag: Optional[List[str]],
79
82
  dry_run: Optional[bool],
80
83
  strict: Optional[bool],
84
+ workspace: Optional[str],
81
85
  ) -> None:
82
86
  """
83
87
  Push Workflows to Vellum. If a module is provided, only the Workflow for that module will be pushed.
@@ -93,6 +97,7 @@ def workflows_push(
93
97
  release_tags=release_tag,
94
98
  dry_run=dry_run,
95
99
  strict=strict,
100
+ workspace=workspace,
96
101
  )
97
102
 
98
103
 
@@ -113,6 +118,7 @@ def workflows_push(
113
118
  is_flag=True,
114
119
  help="Raises an error if we detect an unexpected discrepancy in the generated artifact.",
115
120
  )
121
+ @click.option("--workspace", type=str, help="The specific Workspace config to use when pushing")
116
122
  def push_module(
117
123
  ctx: click.Context,
118
124
  deploy: Optional[bool],
@@ -122,6 +128,7 @@ def push_module(
122
128
  release_tag: Optional[List[str]],
123
129
  dry_run: Optional[bool],
124
130
  strict: Optional[bool],
131
+ workspace: Optional[str],
125
132
  ) -> None:
126
133
  """Push a specific module to Vellum"""
127
134
 
@@ -135,6 +142,7 @@ def push_module(
135
142
  release_tags=release_tag,
136
143
  dry_run=dry_run,
137
144
  strict=strict,
145
+ workspace=workspace,
138
146
  )
139
147
 
140
148
 
vellum_cli/config.py CHANGED
@@ -13,6 +13,17 @@ LOCKFILE_PATH = "vellum.lock.json"
13
13
  PYPROJECT_TOML_PATH = "pyproject.toml"
14
14
 
15
15
 
16
+ class WorkspaceConfig(UniversalBaseModel):
17
+ name: str
18
+ api_key: str
19
+
20
+ def merge(self, other: "WorkspaceConfig") -> "WorkspaceConfig":
21
+ return WorkspaceConfig(name=self.name or other.name, api_key=self.api_key or other.api_key)
22
+
23
+
24
+ DEFAULT_WORKSPACE_CONFIG = WorkspaceConfig(name="default", api_key="VELLUM_API_KEY")
25
+
26
+
16
27
  class WorkflowDeploymentConfig(UniversalBaseModel):
17
28
  id: Optional[UUID] = None
18
29
  label: Optional[str] = None
@@ -37,6 +48,7 @@ class WorkflowConfig(UniversalBaseModel):
37
48
  deployments: List[WorkflowDeploymentConfig] = field(default_factory=list)
38
49
  container_image_name: Optional[str] = None
39
50
  container_image_tag: Optional[str] = None
51
+ workspace: str = DEFAULT_WORKSPACE_CONFIG.name
40
52
 
41
53
  def merge(self, other: "WorkflowConfig") -> "WorkflowConfig":
42
54
  self_deployment_by_id = {
@@ -72,12 +84,14 @@ class WorkflowConfig(UniversalBaseModel):
72
84
  deployments=merged_deployments,
73
85
  container_image_tag=self.container_image_tag or other.container_image_tag,
74
86
  container_image_name=self.container_image_name or other.container_image_name,
87
+ workspace=self.workspace or other.workspace,
75
88
  )
76
89
 
77
90
 
78
91
  class VellumCliConfig(UniversalBaseModel):
79
92
  version: Literal["1.0"] = "1.0"
80
93
  workflows: List[WorkflowConfig] = field(default_factory=list)
94
+ workspaces: List[WorkspaceConfig] = field(default_factory=list)
81
95
 
82
96
  def save(self) -> None:
83
97
  lockfile_path = os.path.join(os.getcwd(), LOCKFILE_PATH)
@@ -102,7 +116,21 @@ class VellumCliConfig(UniversalBaseModel):
102
116
  elif other_workflow:
103
117
  merged_workflows.append(other_workflow)
104
118
 
105
- return VellumCliConfig(workflows=merged_workflows, version=self.version)
119
+ self_workspace_by_name = {workspace.name: workspace for workspace in self.workspaces}
120
+ other_workspace_by_name = {workspace.name: workspace for workspace in other.workspaces}
121
+ all_names = sorted(set(self_workspace_by_name.keys()).union(set(other_workspace_by_name.keys())))
122
+ merged_workspaces = []
123
+ for name in all_names:
124
+ self_workspace = self_workspace_by_name.get(name)
125
+ other_workspace = other_workspace_by_name.get(name)
126
+ if self_workspace and other_workspace:
127
+ merged_workspaces.append(self_workspace.merge(other_workspace))
128
+ elif self_workspace:
129
+ merged_workspaces.append(self_workspace)
130
+ elif other_workspace:
131
+ merged_workspaces.append(other_workspace)
132
+
133
+ return VellumCliConfig(workflows=merged_workflows, workspaces=merged_workspaces, version=self.version)
106
134
 
107
135
 
108
136
  def load_vellum_cli_config(root_dir: Optional[str] = None) -> VellumCliConfig:
vellum_cli/push.py CHANGED
@@ -15,7 +15,7 @@ from vellum.types import WorkflowPushDeploymentConfigRequest
15
15
  from vellum.workflows.utils.names import snake_to_title_case
16
16
  from vellum.workflows.vellum_client import create_vellum_client
17
17
  from vellum.workflows.workflows.base import BaseWorkflow
18
- from vellum_cli.config import WorkflowDeploymentConfig, load_vellum_cli_config
18
+ from vellum_cli.config import DEFAULT_WORKSPACE_CONFIG, WorkflowConfig, WorkflowDeploymentConfig, load_vellum_cli_config
19
19
  from vellum_cli.logger import load_cli_logger
20
20
  from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
21
21
  from vellum_ee.workflows.display.workflows.vellum_workflow_display import VellumWorkflowDisplay
@@ -30,8 +30,9 @@ def push_command(
30
30
  release_tags: Optional[List[str]] = None,
31
31
  dry_run: Optional[bool] = None,
32
32
  strict: Optional[bool] = None,
33
+ workspace: Optional[str] = None,
33
34
  ) -> None:
34
- load_dotenv()
35
+ load_dotenv(dotenv_path=os.path.join(os.getcwd(), ".env"))
35
36
  logger = load_cli_logger()
36
37
  config = load_vellum_cli_config()
37
38
 
@@ -46,7 +47,27 @@ def push_command(
46
47
  raise ValueError(f"No workflow config for '{module}' found in project to push.")
47
48
 
48
49
  logger.info(f"Loading workflow from {workflow_config.module}")
49
- client = create_vellum_client()
50
+ resolved_workspace = workspace or workflow_config.workspace or DEFAULT_WORKSPACE_CONFIG.name
51
+ workspace_config = (
52
+ next((w for w in config.workspaces if w.name == resolved_workspace), DEFAULT_WORKSPACE_CONFIG)
53
+ if workspace
54
+ else DEFAULT_WORKSPACE_CONFIG
55
+ )
56
+ api_key = os.getenv(workspace_config.api_key)
57
+ if not api_key:
58
+ raise ValueError(f"No API key value found in environment for workspace '{workspace_config.name}'.")
59
+
60
+ if workspace_config.name != workflow_config.workspace:
61
+ # We are pushing to a new workspace, so we need a new workflow config
62
+ workflow_config = WorkflowConfig(
63
+ module=workflow_config.module,
64
+ workspace=workspace_config.name,
65
+ )
66
+ config.workflows.append(workflow_config)
67
+
68
+ client = create_vellum_client(
69
+ api_key=api_key,
70
+ )
50
71
  sys.path.insert(0, os.getcwd())
51
72
 
52
73
  # Remove this once we could serialize using the artifact in Vembda
@@ -46,6 +46,9 @@ def mock_module(request) -> Generator[MockModuleResult, None, None]:
46
46
  }
47
47
  )
48
48
 
49
+ with open(os.path.join(temp_dir, ".env"), "w") as f:
50
+ f.write("VELLUM_API_KEY=abcdef123456")
51
+
49
52
  yield MockModuleResult(
50
53
  temp_dir=temp_dir,
51
54
  module=module,
@@ -124,6 +124,7 @@ def test_pull__sandbox_id_with_no_config(vellum_client):
124
124
  lock_data = json.loads(f.read())
125
125
  assert lock_data == {
126
126
  "version": "1.0",
127
+ "workspaces": [],
127
128
  "workflows": [
128
129
  {
129
130
  "module": "workflow_87654321",
@@ -132,6 +133,7 @@ def test_pull__sandbox_id_with_no_config(vellum_client):
132
133
  "deployments": [],
133
134
  "container_image_tag": None,
134
135
  "container_image_name": None,
136
+ "workspace": "default",
135
137
  }
136
138
  ],
137
139
  }
@@ -208,8 +210,10 @@ def test_pull__workflow_deployment_with_no_config(vellum_client):
208
210
  "deployments": [],
209
211
  "container_image_tag": None,
210
212
  "container_image_name": None,
213
+ "workspace": "default",
211
214
  }
212
215
  ],
216
+ "workspaces": [],
213
217
  }
214
218
 
215
219
 
@@ -449,6 +453,7 @@ def test_pull__sandbox_id_with_other_workflow_deployment_in_lock(vellum_client,
449
453
  ],
450
454
  "container_image_name": None,
451
455
  "container_image_tag": None,
456
+ "workspace": "default",
452
457
  },
453
458
  {
454
459
  "module": "workflow_87654321",
@@ -457,6 +462,7 @@ def test_pull__sandbox_id_with_other_workflow_deployment_in_lock(vellum_client,
457
462
  "deployments": [],
458
463
  "container_image_name": "test",
459
464
  "container_image_tag": "1.0",
465
+ "workspace": "default",
460
466
  },
461
467
  ]
462
468