vellum-ai 0.14.34__py3-none-any.whl → 0.14.36__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 (27) hide show
  1. vellum/__init__.py +8 -0
  2. vellum/client/__init__.py +4 -4
  3. vellum/client/core/client_wrapper.py +1 -1
  4. vellum/client/resources/release_reviews/client.py +118 -1
  5. vellum/client/types/__init__.py +8 -0
  6. vellum/client/types/prompt_deployment_release.py +34 -0
  7. vellum/client/types/prompt_deployment_release_prompt_deployment.py +19 -0
  8. vellum/client/types/prompt_deployment_release_prompt_version.py +19 -0
  9. vellum/client/types/workflow_deployment_release.py +2 -0
  10. vellum/client/types/workflow_deployment_release_workflow_deployment.py +19 -0
  11. vellum/types/prompt_deployment_release.py +3 -0
  12. vellum/types/prompt_deployment_release_prompt_deployment.py +3 -0
  13. vellum/types/prompt_deployment_release_prompt_version.py +3 -0
  14. vellum/types/workflow_deployment_release_workflow_deployment.py +3 -0
  15. vellum/workflows/nodes/displayable/guardrail_node/node.py +21 -6
  16. vellum/workflows/nodes/displayable/guardrail_node/test_node.py +63 -0
  17. vellum/workflows/nodes/displayable/prompt_deployment_node/node.py +14 -2
  18. vellum/workflows/nodes/displayable/prompt_deployment_node/tests/test_node.py +43 -0
  19. vellum/workflows/state/base.py +7 -1
  20. vellum/workflows/state/tests/test_state.py +49 -0
  21. {vellum_ai-0.14.34.dist-info → vellum_ai-0.14.36.dist-info}/METADATA +1 -1
  22. {vellum_ai-0.14.34.dist-info → vellum_ai-0.14.36.dist-info}/RECORD +27 -19
  23. vellum_cli/pull.py +3 -0
  24. vellum_cli/tests/test_pull.py +4 -1
  25. {vellum_ai-0.14.34.dist-info → vellum_ai-0.14.36.dist-info}/LICENSE +0 -0
  26. {vellum_ai-0.14.34.dist-info → vellum_ai-0.14.36.dist-info}/WHEEL +0 -0
  27. {vellum_ai-0.14.34.dist-info → vellum_ai-0.14.36.dist-info}/entry_points.txt +0 -0
vellum/__init__.py CHANGED
@@ -300,6 +300,9 @@ from .types import (
300
300
  PromptDeploymentExpandMetaRequest,
301
301
  PromptDeploymentInputRequest,
302
302
  PromptDeploymentParentContext,
303
+ PromptDeploymentRelease,
304
+ PromptDeploymentReleasePromptDeployment,
305
+ PromptDeploymentReleasePromptVersion,
303
306
  PromptExecConfig,
304
307
  PromptExecutionMeta,
305
308
  PromptNodeExecutionMeta,
@@ -507,6 +510,7 @@ from .types import (
507
510
  WorkflowDeploymentParentContext,
508
511
  WorkflowDeploymentRead,
509
512
  WorkflowDeploymentRelease,
513
+ WorkflowDeploymentReleaseWorkflowDeployment,
510
514
  WorkflowDeploymentReleaseWorkflowVersion,
511
515
  WorkflowError,
512
516
  WorkflowEventDisplayContext,
@@ -921,6 +925,9 @@ __all__ = [
921
925
  "PromptDeploymentExpandMetaRequest",
922
926
  "PromptDeploymentInputRequest",
923
927
  "PromptDeploymentParentContext",
928
+ "PromptDeploymentRelease",
929
+ "PromptDeploymentReleasePromptDeployment",
930
+ "PromptDeploymentReleasePromptVersion",
924
931
  "PromptExecConfig",
925
932
  "PromptExecutionMeta",
926
933
  "PromptNodeExecutionMeta",
@@ -1130,6 +1137,7 @@ __all__ = [
1130
1137
  "WorkflowDeploymentParentContext",
1131
1138
  "WorkflowDeploymentRead",
1132
1139
  "WorkflowDeploymentRelease",
1140
+ "WorkflowDeploymentReleaseWorkflowDeployment",
1133
1141
  "WorkflowDeploymentReleaseWorkflowVersion",
1134
1142
  "WorkflowDeploymentsListRequestStatus",
1135
1143
  "WorkflowError",
vellum/client/__init__.py CHANGED
@@ -7,6 +7,7 @@ from .core.client_wrapper import SyncClientWrapper
7
7
  from .resources.ad_hoc.client import AdHocClient
8
8
  from .resources.container_images.client import ContainerImagesClient
9
9
  from .resources.deployments.client import DeploymentsClient
10
+ from .resources.release_reviews.client import ReleaseReviewsClient
10
11
  from .resources.document_indexes.client import DocumentIndexesClient
11
12
  from .resources.documents.client import DocumentsClient
12
13
  from .resources.folder_entities.client import FolderEntitiesClient
@@ -18,7 +19,6 @@ from .resources.sandboxes.client import SandboxesClient
18
19
  from .resources.test_suite_runs.client import TestSuiteRunsClient
19
20
  from .resources.test_suites.client import TestSuitesClient
20
21
  from .resources.workflow_deployments.client import WorkflowDeploymentsClient
21
- from .resources.release_reviews.client import ReleaseReviewsClient
22
22
  from .resources.workflow_sandboxes.client import WorkflowSandboxesClient
23
23
  from .resources.workflows.client import WorkflowsClient
24
24
  from .resources.workspace_secrets.client import WorkspaceSecretsClient
@@ -65,6 +65,7 @@ from .core.client_wrapper import AsyncClientWrapper
65
65
  from .resources.ad_hoc.client import AsyncAdHocClient
66
66
  from .resources.container_images.client import AsyncContainerImagesClient
67
67
  from .resources.deployments.client import AsyncDeploymentsClient
68
+ from .resources.release_reviews.client import AsyncReleaseReviewsClient
68
69
  from .resources.document_indexes.client import AsyncDocumentIndexesClient
69
70
  from .resources.documents.client import AsyncDocumentsClient
70
71
  from .resources.folder_entities.client import AsyncFolderEntitiesClient
@@ -76,7 +77,6 @@ from .resources.sandboxes.client import AsyncSandboxesClient
76
77
  from .resources.test_suite_runs.client import AsyncTestSuiteRunsClient
77
78
  from .resources.test_suites.client import AsyncTestSuitesClient
78
79
  from .resources.workflow_deployments.client import AsyncWorkflowDeploymentsClient
79
- from .resources.release_reviews.client import AsyncReleaseReviewsClient
80
80
  from .resources.workflow_sandboxes.client import AsyncWorkflowSandboxesClient
81
81
  from .resources.workflows.client import AsyncWorkflowsClient
82
82
  from .resources.workspace_secrets.client import AsyncWorkspaceSecretsClient
@@ -143,6 +143,7 @@ class Vellum:
143
143
  self.ad_hoc = AdHocClient(client_wrapper=self._client_wrapper)
144
144
  self.container_images = ContainerImagesClient(client_wrapper=self._client_wrapper)
145
145
  self.deployments = DeploymentsClient(client_wrapper=self._client_wrapper)
146
+ self.release_reviews = ReleaseReviewsClient(client_wrapper=self._client_wrapper)
146
147
  self.document_indexes = DocumentIndexesClient(client_wrapper=self._client_wrapper)
147
148
  self.documents = DocumentsClient(client_wrapper=self._client_wrapper)
148
149
  self.folder_entities = FolderEntitiesClient(client_wrapper=self._client_wrapper)
@@ -154,7 +155,6 @@ class Vellum:
154
155
  self.test_suite_runs = TestSuiteRunsClient(client_wrapper=self._client_wrapper)
155
156
  self.test_suites = TestSuitesClient(client_wrapper=self._client_wrapper)
156
157
  self.workflow_deployments = WorkflowDeploymentsClient(client_wrapper=self._client_wrapper)
157
- self.release_reviews = ReleaseReviewsClient(client_wrapper=self._client_wrapper)
158
158
  self.workflow_sandboxes = WorkflowSandboxesClient(client_wrapper=self._client_wrapper)
159
159
  self.workflows = WorkflowsClient(client_wrapper=self._client_wrapper)
160
160
  self.workspace_secrets = WorkspaceSecretsClient(client_wrapper=self._client_wrapper)
@@ -1486,6 +1486,7 @@ class AsyncVellum:
1486
1486
  self.ad_hoc = AsyncAdHocClient(client_wrapper=self._client_wrapper)
1487
1487
  self.container_images = AsyncContainerImagesClient(client_wrapper=self._client_wrapper)
1488
1488
  self.deployments = AsyncDeploymentsClient(client_wrapper=self._client_wrapper)
1489
+ self.release_reviews = AsyncReleaseReviewsClient(client_wrapper=self._client_wrapper)
1489
1490
  self.document_indexes = AsyncDocumentIndexesClient(client_wrapper=self._client_wrapper)
1490
1491
  self.documents = AsyncDocumentsClient(client_wrapper=self._client_wrapper)
1491
1492
  self.folder_entities = AsyncFolderEntitiesClient(client_wrapper=self._client_wrapper)
@@ -1497,7 +1498,6 @@ class AsyncVellum:
1497
1498
  self.test_suite_runs = AsyncTestSuiteRunsClient(client_wrapper=self._client_wrapper)
1498
1499
  self.test_suites = AsyncTestSuitesClient(client_wrapper=self._client_wrapper)
1499
1500
  self.workflow_deployments = AsyncWorkflowDeploymentsClient(client_wrapper=self._client_wrapper)
1500
- self.release_reviews = AsyncReleaseReviewsClient(client_wrapper=self._client_wrapper)
1501
1501
  self.workflow_sandboxes = AsyncWorkflowSandboxesClient(client_wrapper=self._client_wrapper)
1502
1502
  self.workflows = AsyncWorkflowsClient(client_wrapper=self._client_wrapper)
1503
1503
  self.workspace_secrets = AsyncWorkspaceSecretsClient(client_wrapper=self._client_wrapper)
@@ -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.14.34",
21
+ "X-Fern-SDK-Version": "0.14.36",
22
22
  }
23
23
  headers["X_API_KEY"] = self.api_key
24
24
  return headers
@@ -3,11 +3,12 @@
3
3
  from ...core.client_wrapper import SyncClientWrapper
4
4
  import typing
5
5
  from ...core.request_options import RequestOptions
6
- from ...types.workflow_deployment_release import WorkflowDeploymentRelease
6
+ from ...types.prompt_deployment_release import PromptDeploymentRelease
7
7
  from ...core.jsonable_encoder import jsonable_encoder
8
8
  from ...core.pydantic_utilities import parse_obj_as
9
9
  from json.decoder import JSONDecodeError
10
10
  from ...core.api_error import ApiError
11
+ from ...types.workflow_deployment_release import WorkflowDeploymentRelease
11
12
  from ...core.client_wrapper import AsyncClientWrapper
12
13
 
13
14
 
@@ -15,6 +16,60 @@ class ReleaseReviewsClient:
15
16
  def __init__(self, *, client_wrapper: SyncClientWrapper):
16
17
  self._client_wrapper = client_wrapper
17
18
 
19
+ def retrieve_prompt_deployment_release(
20
+ self, id: str, release_id_or_release_tag: str, *, request_options: typing.Optional[RequestOptions] = None
21
+ ) -> PromptDeploymentRelease:
22
+ """
23
+ Retrieve a specific Prompt Deployment Release by either its UUID or the name of a Release Tag that points to it.
24
+
25
+ Parameters
26
+ ----------
27
+ id : str
28
+ A UUID string identifying this deployment.
29
+
30
+ release_id_or_release_tag : str
31
+ Either the UUID of Prompt Deployment Release you'd like to retrieve, or the name of a Release Tag that's pointing to the Prompt Deployment Release you'd like to retrieve.
32
+
33
+ request_options : typing.Optional[RequestOptions]
34
+ Request-specific configuration.
35
+
36
+ Returns
37
+ -------
38
+ PromptDeploymentRelease
39
+
40
+
41
+ Examples
42
+ --------
43
+ from vellum import Vellum
44
+
45
+ client = Vellum(
46
+ api_key="YOUR_API_KEY",
47
+ )
48
+ client.release_reviews.retrieve_prompt_deployment_release(
49
+ id="id",
50
+ release_id_or_release_tag="release_id_or_release_tag",
51
+ )
52
+ """
53
+ _response = self._client_wrapper.httpx_client.request(
54
+ f"v1/deployments/{jsonable_encoder(id)}/releases/{jsonable_encoder(release_id_or_release_tag)}",
55
+ base_url=self._client_wrapper.get_environment().default,
56
+ method="GET",
57
+ request_options=request_options,
58
+ )
59
+ try:
60
+ if 200 <= _response.status_code < 300:
61
+ return typing.cast(
62
+ PromptDeploymentRelease,
63
+ parse_obj_as(
64
+ type_=PromptDeploymentRelease, # type: ignore
65
+ object_=_response.json(),
66
+ ),
67
+ )
68
+ _response_json = _response.json()
69
+ except JSONDecodeError:
70
+ raise ApiError(status_code=_response.status_code, body=_response.text)
71
+ raise ApiError(status_code=_response.status_code, body=_response_json)
72
+
18
73
  def retrieve_workflow_deployment_release(
19
74
  self, id: str, release_id_or_release_tag: str, *, request_options: typing.Optional[RequestOptions] = None
20
75
  ) -> WorkflowDeploymentRelease:
@@ -74,6 +129,68 @@ class AsyncReleaseReviewsClient:
74
129
  def __init__(self, *, client_wrapper: AsyncClientWrapper):
75
130
  self._client_wrapper = client_wrapper
76
131
 
132
+ async def retrieve_prompt_deployment_release(
133
+ self, id: str, release_id_or_release_tag: str, *, request_options: typing.Optional[RequestOptions] = None
134
+ ) -> PromptDeploymentRelease:
135
+ """
136
+ Retrieve a specific Prompt Deployment Release by either its UUID or the name of a Release Tag that points to it.
137
+
138
+ Parameters
139
+ ----------
140
+ id : str
141
+ A UUID string identifying this deployment.
142
+
143
+ release_id_or_release_tag : str
144
+ Either the UUID of Prompt Deployment Release you'd like to retrieve, or the name of a Release Tag that's pointing to the Prompt Deployment Release you'd like to retrieve.
145
+
146
+ request_options : typing.Optional[RequestOptions]
147
+ Request-specific configuration.
148
+
149
+ Returns
150
+ -------
151
+ PromptDeploymentRelease
152
+
153
+
154
+ Examples
155
+ --------
156
+ import asyncio
157
+
158
+ from vellum import AsyncVellum
159
+
160
+ client = AsyncVellum(
161
+ api_key="YOUR_API_KEY",
162
+ )
163
+
164
+
165
+ async def main() -> None:
166
+ await client.release_reviews.retrieve_prompt_deployment_release(
167
+ id="id",
168
+ release_id_or_release_tag="release_id_or_release_tag",
169
+ )
170
+
171
+
172
+ asyncio.run(main())
173
+ """
174
+ _response = await self._client_wrapper.httpx_client.request(
175
+ f"v1/deployments/{jsonable_encoder(id)}/releases/{jsonable_encoder(release_id_or_release_tag)}",
176
+ base_url=self._client_wrapper.get_environment().default,
177
+ method="GET",
178
+ request_options=request_options,
179
+ )
180
+ try:
181
+ if 200 <= _response.status_code < 300:
182
+ return typing.cast(
183
+ PromptDeploymentRelease,
184
+ parse_obj_as(
185
+ type_=PromptDeploymentRelease, # type: ignore
186
+ object_=_response.json(),
187
+ ),
188
+ )
189
+ _response_json = _response.json()
190
+ except JSONDecodeError:
191
+ raise ApiError(status_code=_response.status_code, body=_response.text)
192
+ raise ApiError(status_code=_response.status_code, body=_response_json)
193
+
77
194
  async def retrieve_workflow_deployment_release(
78
195
  self, id: str, release_id_or_release_tag: str, *, request_options: typing.Optional[RequestOptions] = None
79
196
  ) -> WorkflowDeploymentRelease:
@@ -308,6 +308,9 @@ from .prompt_block_state import PromptBlockState
308
308
  from .prompt_deployment_expand_meta_request import PromptDeploymentExpandMetaRequest
309
309
  from .prompt_deployment_input_request import PromptDeploymentInputRequest
310
310
  from .prompt_deployment_parent_context import PromptDeploymentParentContext
311
+ from .prompt_deployment_release import PromptDeploymentRelease
312
+ from .prompt_deployment_release_prompt_deployment import PromptDeploymentReleasePromptDeployment
313
+ from .prompt_deployment_release_prompt_version import PromptDeploymentReleasePromptVersion
311
314
  from .prompt_exec_config import PromptExecConfig
312
315
  from .prompt_execution_meta import PromptExecutionMeta
313
316
  from .prompt_node_execution_meta import PromptNodeExecutionMeta
@@ -531,6 +534,7 @@ from .workflow_deployment_history_item import WorkflowDeploymentHistoryItem
531
534
  from .workflow_deployment_parent_context import WorkflowDeploymentParentContext
532
535
  from .workflow_deployment_read import WorkflowDeploymentRead
533
536
  from .workflow_deployment_release import WorkflowDeploymentRelease
537
+ from .workflow_deployment_release_workflow_deployment import WorkflowDeploymentReleaseWorkflowDeployment
534
538
  from .workflow_deployment_release_workflow_version import WorkflowDeploymentReleaseWorkflowVersion
535
539
  from .workflow_error import WorkflowError
536
540
  from .workflow_event_display_context import WorkflowEventDisplayContext
@@ -901,6 +905,9 @@ __all__ = [
901
905
  "PromptDeploymentExpandMetaRequest",
902
906
  "PromptDeploymentInputRequest",
903
907
  "PromptDeploymentParentContext",
908
+ "PromptDeploymentRelease",
909
+ "PromptDeploymentReleasePromptDeployment",
910
+ "PromptDeploymentReleasePromptVersion",
904
911
  "PromptExecConfig",
905
912
  "PromptExecutionMeta",
906
913
  "PromptNodeExecutionMeta",
@@ -1108,6 +1115,7 @@ __all__ = [
1108
1115
  "WorkflowDeploymentParentContext",
1109
1116
  "WorkflowDeploymentRead",
1110
1117
  "WorkflowDeploymentRelease",
1118
+ "WorkflowDeploymentReleaseWorkflowDeployment",
1111
1119
  "WorkflowDeploymentReleaseWorkflowVersion",
1112
1120
  "WorkflowError",
1113
1121
  "WorkflowEventDisplayContext",
@@ -0,0 +1,34 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from ..core.pydantic_utilities import UniversalBaseModel
4
+ import datetime as dt
5
+ from .release_environment import ReleaseEnvironment
6
+ import typing
7
+ from .release_created_by import ReleaseCreatedBy
8
+ from .prompt_deployment_release_prompt_version import PromptDeploymentReleasePromptVersion
9
+ from .prompt_deployment_release_prompt_deployment import PromptDeploymentReleasePromptDeployment
10
+ from .release_release_tag import ReleaseReleaseTag
11
+ from .slim_release_review import SlimReleaseReview
12
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2
13
+ import pydantic
14
+
15
+
16
+ class PromptDeploymentRelease(UniversalBaseModel):
17
+ id: str
18
+ created: dt.datetime
19
+ environment: ReleaseEnvironment
20
+ created_by: typing.Optional[ReleaseCreatedBy] = None
21
+ prompt_version: PromptDeploymentReleasePromptVersion
22
+ deployment: PromptDeploymentReleasePromptDeployment
23
+ description: typing.Optional[str] = None
24
+ release_tags: typing.List[ReleaseReleaseTag]
25
+ reviews: typing.List[SlimReleaseReview]
26
+
27
+ if IS_PYDANTIC_V2:
28
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
29
+ else:
30
+
31
+ class Config:
32
+ frozen = True
33
+ smart_union = True
34
+ extra = pydantic.Extra.allow
@@ -0,0 +1,19 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from ..core.pydantic_utilities import UniversalBaseModel
4
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2
5
+ import typing
6
+ import pydantic
7
+
8
+
9
+ class PromptDeploymentReleasePromptDeployment(UniversalBaseModel):
10
+ name: str
11
+
12
+ if IS_PYDANTIC_V2:
13
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
14
+ else:
15
+
16
+ class Config:
17
+ frozen = True
18
+ smart_union = True
19
+ extra = pydantic.Extra.allow
@@ -0,0 +1,19 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from ..core.pydantic_utilities import UniversalBaseModel
4
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2
5
+ import typing
6
+ import pydantic
7
+
8
+
9
+ class PromptDeploymentReleasePromptVersion(UniversalBaseModel):
10
+ id: str
11
+
12
+ if IS_PYDANTIC_V2:
13
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
14
+ else:
15
+
16
+ class Config:
17
+ frozen = True
18
+ smart_union = True
19
+ extra = pydantic.Extra.allow
@@ -8,6 +8,7 @@ from .release_environment import ReleaseEnvironment
8
8
  import typing
9
9
  from .release_created_by import ReleaseCreatedBy
10
10
  from .workflow_deployment_release_workflow_version import WorkflowDeploymentReleaseWorkflowVersion
11
+ from .workflow_deployment_release_workflow_deployment import WorkflowDeploymentReleaseWorkflowDeployment
11
12
  from .release_release_tag import ReleaseReleaseTag
12
13
  from .slim_release_review import SlimReleaseReview
13
14
  from ..core.pydantic_utilities import IS_PYDANTIC_V2
@@ -21,6 +22,7 @@ class WorkflowDeploymentRelease(UniversalBaseModel):
21
22
  environment: ReleaseEnvironment
22
23
  created_by: typing.Optional[ReleaseCreatedBy] = None
23
24
  workflow_version: WorkflowDeploymentReleaseWorkflowVersion
25
+ deployment: WorkflowDeploymentReleaseWorkflowDeployment
24
26
  description: typing.Optional[str] = None
25
27
  release_tags: typing.List[ReleaseReleaseTag]
26
28
  reviews: typing.List[SlimReleaseReview]
@@ -0,0 +1,19 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from ..core.pydantic_utilities import UniversalBaseModel
4
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2
5
+ import typing
6
+ import pydantic
7
+
8
+
9
+ class WorkflowDeploymentReleaseWorkflowDeployment(UniversalBaseModel):
10
+ name: str
11
+
12
+ if IS_PYDANTIC_V2:
13
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
14
+ else:
15
+
16
+ class Config:
17
+ frozen = True
18
+ smart_union = True
19
+ extra = pydantic.Extra.allow
@@ -0,0 +1,3 @@
1
+ # WARNING: This file will be removed in a future release. Please import from "vellum.client" instead.
2
+
3
+ from vellum.client.types.prompt_deployment_release import *
@@ -0,0 +1,3 @@
1
+ # WARNING: This file will be removed in a future release. Please import from "vellum.client" instead.
2
+
3
+ from vellum.client.types.prompt_deployment_release_prompt_deployment import *
@@ -0,0 +1,3 @@
1
+ # WARNING: This file will be removed in a future release. Please import from "vellum.client" instead.
2
+
3
+ from vellum.client.types.prompt_deployment_release_prompt_version import *
@@ -0,0 +1,3 @@
1
+ # WARNING: This file will be removed in a future release. Please import from "vellum.client" instead.
2
+
3
+ from vellum.client.types.workflow_deployment_release_workflow_deployment import *
@@ -34,6 +34,7 @@ class GuardrailNode(BaseNode[StateType], Generic[StateType]):
34
34
 
35
35
  class Outputs(BaseOutputs):
36
36
  score: float
37
+ normalized_score: Optional[float]
37
38
  log: Optional[str]
38
39
 
39
40
  def run(self) -> Outputs:
@@ -46,16 +47,30 @@ class GuardrailNode(BaseNode[StateType], Generic[StateType]):
46
47
 
47
48
  metric_outputs = {output.name: output.value for output in metric_execution.outputs}
48
49
 
49
- score = metric_outputs.get("score")
50
+ SCORE_KEY = "score"
51
+ NORMALIZED_SCORE_KEY = "normalized_score"
52
+ LOG_KEY = "log"
53
+
54
+ score = metric_outputs.get(SCORE_KEY)
50
55
  if not isinstance(score, float):
51
56
  raise NodeException(
52
- message="Metric execution must have one output named 'score' with type 'float'",
57
+ message=f"Metric execution must have one output named '{SCORE_KEY}' with type 'float'",
53
58
  code=WorkflowErrorCode.INVALID_OUTPUTS,
54
59
  )
55
- metric_outputs.pop("score")
60
+ metric_outputs.pop(SCORE_KEY)
61
+
62
+ if NORMALIZED_SCORE_KEY in metric_outputs:
63
+ normalized_score = metric_outputs.pop(NORMALIZED_SCORE_KEY)
64
+ if not isinstance(normalized_score, float):
65
+ raise NodeException(
66
+ message=f"Metric execution must have one output named '{NORMALIZED_SCORE_KEY}' with type 'float'",
67
+ code=WorkflowErrorCode.INVALID_OUTPUTS,
68
+ )
69
+ else:
70
+ normalized_score = None
56
71
 
57
- if "log" in metric_outputs:
58
- log = metric_outputs.pop("log") or ""
72
+ if LOG_KEY in metric_outputs:
73
+ log = metric_outputs.pop(LOG_KEY) or ""
59
74
  if not isinstance(log, str):
60
75
  raise NodeException(
61
76
  message="Metric execution log output must be of type 'str'",
@@ -64,7 +79,7 @@ class GuardrailNode(BaseNode[StateType], Generic[StateType]):
64
79
  else:
65
80
  log = None
66
81
 
67
- return self.Outputs(score=score, log=log, **metric_outputs)
82
+ return self.Outputs(score=score, normalized_score=normalized_score, log=log, **metric_outputs)
68
83
 
69
84
  def _compile_metric_inputs(self) -> List[MetricDefinitionInput]:
70
85
  # TODO: We may want to consolidate with prompt deployment input compilation
@@ -3,6 +3,8 @@ import pytest
3
3
  from vellum import TestSuiteRunMetricNumberOutput
4
4
  from vellum.client.types.metric_definition_execution import MetricDefinitionExecution
5
5
  from vellum.client.types.test_suite_run_metric_string_output import TestSuiteRunMetricStringOutput
6
+ from vellum.workflows.errors import WorkflowErrorCode
7
+ from vellum.workflows.exceptions import NodeException
6
8
  from vellum.workflows.nodes.displayable.guardrail_node.node import GuardrailNode
7
9
 
8
10
 
@@ -36,3 +38,64 @@ def test_run_guardrail_node__empty_log(vellum_client, log_value):
36
38
  # THEN the workflow should have completed successfully
37
39
  assert outputs.score == 0.6
38
40
  assert outputs.log == ""
41
+
42
+
43
+ def test_run_guardrail_node__normalized_score(vellum_client):
44
+ """Confirm that we can successfully invoke a Guardrail Node"""
45
+
46
+ # GIVEN a Guardrail Node
47
+ class MyGuard(GuardrailNode):
48
+ metric_definition = "example_metric_definition"
49
+ metric_inputs = {}
50
+
51
+ # AND we know that the guardrail node will return a normalized score
52
+ mock_metric_execution = MetricDefinitionExecution(
53
+ outputs=[
54
+ TestSuiteRunMetricNumberOutput(
55
+ name="score",
56
+ value=0.6,
57
+ ),
58
+ TestSuiteRunMetricNumberOutput(
59
+ name="normalized_score",
60
+ value=1.0,
61
+ ),
62
+ ],
63
+ )
64
+ vellum_client.metric_definitions.execute_metric_definition.return_value = mock_metric_execution
65
+
66
+ # WHEN we run the Guardrail Node
67
+ outputs = MyGuard().run()
68
+
69
+ # THEN the workflow should have completed successfully
70
+ assert outputs.score == 0.6
71
+ assert outputs.normalized_score == 1.0
72
+
73
+
74
+ def test_run_guardrail_node__normalized_score_null(vellum_client):
75
+ # GIVEN a Guardrail Node
76
+ class MyGuard(GuardrailNode):
77
+ metric_definition = "example_metric_definition"
78
+ metric_inputs = {}
79
+
80
+ # AND we know that the guardrail node will return a normalized score that is None
81
+ mock_metric_execution = MetricDefinitionExecution(
82
+ outputs=[
83
+ TestSuiteRunMetricNumberOutput(
84
+ name="score",
85
+ value=0.6,
86
+ ),
87
+ TestSuiteRunMetricNumberOutput(
88
+ name="normalized_score",
89
+ value=None,
90
+ ),
91
+ ],
92
+ )
93
+ vellum_client.metric_definitions.execute_metric_definition.return_value = mock_metric_execution
94
+
95
+ # WHEN we run the Guardrail Node
96
+ with pytest.raises(NodeException) as exc_info:
97
+ MyGuard().run()
98
+
99
+ # THEN we get an exception
100
+ assert exc_info.value.message == "Metric execution must have one output named 'normalized_score' with type 'float'"
101
+ assert exc_info.value.code == WorkflowErrorCode.INVALID_OUTPUTS
@@ -1,6 +1,7 @@
1
1
  import json
2
- from typing import Iterator
2
+ from typing import Any, Dict, Iterator, Type, Union
3
3
 
4
+ from vellum.workflows.constants import undefined
4
5
  from vellum.workflows.errors import WorkflowErrorCode
5
6
  from vellum.workflows.exceptions import NodeException
6
7
  from vellum.workflows.nodes.displayable.bases import BasePromptDeploymentNode as BasePromptDeploymentNode
@@ -11,7 +12,7 @@ from vellum.workflows.types.generics import StateType
11
12
 
12
13
  class PromptDeploymentNode(BasePromptDeploymentNode[StateType]):
13
14
  """
14
- Used to execute a Prompt Deployment and surface a string output for convenience.
15
+ Used to execute a Prompt Deployment and surface a string output and json output if applicable for convenience.
15
16
 
16
17
  prompt_inputs: EntityInputsInterface - The inputs for the Prompt
17
18
  deployment: Union[UUID, str] - Either the Prompt Deployment's UUID or its name.
@@ -33,9 +34,11 @@ class PromptDeploymentNode(BasePromptDeploymentNode[StateType]):
33
34
  The outputs of the PromptDeploymentNode.
34
35
 
35
36
  text: str - The result of the Prompt Execution
37
+ json: Optional[Dict[Any, Any]] - The result of the Prompt Execution in JSON format
36
38
  """
37
39
 
38
40
  text: str
41
+ json: Union[Dict[Any, Any], Type[undefined]] = undefined
39
42
 
40
43
  def run(self) -> Iterator[BaseOutput]:
41
44
  outputs = yield from self._process_prompt_event_stream()
@@ -46,12 +49,18 @@ class PromptDeploymentNode(BasePromptDeploymentNode[StateType]):
46
49
  )
47
50
 
48
51
  string_outputs = []
52
+ json_output = None
53
+
49
54
  for output in outputs:
50
55
  if output.value is None:
51
56
  continue
52
57
 
53
58
  if output.type == "STRING":
54
59
  string_outputs.append(output.value)
60
+ try:
61
+ json_output = json.loads(output.value)
62
+ except (json.JSONDecodeError, TypeError):
63
+ pass
55
64
  elif output.type == "JSON":
56
65
  string_outputs.append(json.dumps(output.value, indent=4))
57
66
  elif output.type == "FUNCTION_CALL":
@@ -61,3 +70,6 @@ class PromptDeploymentNode(BasePromptDeploymentNode[StateType]):
61
70
 
62
71
  value = "\n".join(string_outputs)
63
72
  yield BaseOutput(name="text", value=value)
73
+
74
+ if json_output:
75
+ yield BaseOutput(name="json", value=json_output)
@@ -151,3 +151,46 @@ def test_prompt_deployment_node__parent_context_serialization(mock_httpx_transpo
151
151
  request_execution_context = json.loads(call_request_args.read().decode("utf-8"))["execution_context"]
152
152
  assert request_execution_context["trace_id"] == str(trace_id)
153
153
  assert request_execution_context["parent_context"]
154
+
155
+
156
+ def test_prompt_deployment_node__json_output(vellum_client):
157
+ # GIVEN a PromptDeploymentNode
158
+ class MyPromptDeploymentNode(PromptDeploymentNode):
159
+ deployment = "example_prompt_deployment"
160
+ prompt_inputs = {}
161
+
162
+ # AND a known JSON response from invoking a prompt deployment
163
+ expected_json = {"result": "Hello, world!"}
164
+ expected_outputs: List[PromptOutput] = [
165
+ StringVellumValue(value=json.dumps(expected_json)),
166
+ ]
167
+
168
+ def generate_prompt_events(*args: Any, **kwargs: Any) -> Iterator[ExecutePromptEvent]:
169
+ execution_id = str(uuid4())
170
+ events: List[ExecutePromptEvent] = [
171
+ InitiatedExecutePromptEvent(execution_id=execution_id),
172
+ FulfilledExecutePromptEvent(
173
+ execution_id=execution_id,
174
+ outputs=expected_outputs,
175
+ ),
176
+ ]
177
+ yield from events
178
+
179
+ vellum_client.execute_prompt_stream.side_effect = generate_prompt_events
180
+
181
+ # WHEN the node is run
182
+ node = MyPromptDeploymentNode()
183
+ outputs = [o for o in node.run()]
184
+
185
+ # THEN the node should have produced the outputs we expect
186
+ results_output = outputs[0]
187
+ assert results_output.name == "results"
188
+ assert results_output.value == expected_outputs
189
+
190
+ text_output = outputs[1]
191
+ assert text_output.name == "text"
192
+ assert text_output.value == '{"result": "Hello, world!"}'
193
+
194
+ json_output = outputs[2]
195
+ assert json_output.name == "json"
196
+ assert json_output.value == expected_json
@@ -2,6 +2,7 @@ from collections import defaultdict
2
2
  from copy import deepcopy
3
3
  from dataclasses import field
4
4
  from datetime import datetime
5
+ import logging
5
6
  from queue import Queue
6
7
  from threading import Lock
7
8
  from uuid import UUID, uuid4
@@ -29,6 +30,8 @@ from vellum.workflows.types.utils import (
29
30
  if TYPE_CHECKING:
30
31
  from vellum.workflows.nodes.bases import BaseNode
31
32
 
33
+ logger = logging.getLogger(__name__)
34
+
32
35
 
33
36
  class _Snapshottable:
34
37
  _snapshot_callback: Callable[[], None]
@@ -377,7 +380,10 @@ class BaseState(metaclass=_BaseStateMeta):
377
380
  Snapshots the current state to the workflow emitter. The invoked callback is overridden by the
378
381
  workflow runner.
379
382
  """
380
- self.__snapshot_callback__(deepcopy(self))
383
+ try:
384
+ self.__snapshot_callback__(deepcopy(self))
385
+ except Exception:
386
+ logger.exception("Failed to snapshot Workflow state.")
381
387
 
382
388
  @classmethod
383
389
  def __get_pydantic_core_schema__(
@@ -13,6 +13,16 @@ from vellum.workflows.state.encoder import DefaultStateEncoder
13
13
  snapshot_count: Dict[int, int] = defaultdict(int)
14
14
 
15
15
 
16
+ @pytest.fixture()
17
+ def mock_deepcopy(mocker):
18
+ return mocker.patch("vellum.workflows.state.base.deepcopy")
19
+
20
+
21
+ @pytest.fixture
22
+ def mock_logger(mocker):
23
+ return mocker.patch("vellum.workflows.state.base.logger")
24
+
25
+
16
26
  class MockState(BaseState):
17
27
  foo: str
18
28
  nested_dict: Dict[str, int] = {}
@@ -170,3 +180,42 @@ def test_state_json_serialization__with_queue():
170
180
 
171
181
  # THEN the state is serialized correctly with the queue turned into a list
172
182
  assert json_state["meta"]["node_outputs"] == {"MockNode.Outputs.baz": ["test1", "test2"]}
183
+
184
+
185
+ def test_state_snapshot__deepcopy_fails__logs_error(mock_deepcopy, mock_logger):
186
+ # GIVEN an initial state instance
187
+ class MockState(BaseState):
188
+ foo: str
189
+
190
+ state = MockState(foo="bar")
191
+
192
+ # AND we have a snapshot callback that we are tracking
193
+ snapshot_count = 0
194
+
195
+ def __snapshot_callback__(state: "BaseState") -> None:
196
+ nonlocal snapshot_count
197
+ snapshot_count += 1
198
+
199
+ state.__snapshot_callback__ = __snapshot_callback__
200
+
201
+ # AND deepcopy fails the first time but succeeds the second time
202
+ deepcopy_side_effect_count = 0
203
+
204
+ def side_effect(*args, **kwargs):
205
+ nonlocal deepcopy_side_effect_count
206
+ deepcopy_side_effect_count += 1
207
+ if deepcopy_side_effect_count == 1:
208
+ raise Exception("Failed to deepcopy")
209
+ return deepcopy(args[0])
210
+
211
+ mock_deepcopy.side_effect = side_effect
212
+
213
+ # WHEN we snapshot the state twice
214
+ state.__snapshot__()
215
+ state.__snapshot__()
216
+
217
+ # THEN we were able to invoke the callback once
218
+ assert snapshot_count == 1
219
+
220
+ # AND alert sentry once
221
+ assert mock_logger.exception.call_count == 1
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vellum-ai
3
- Version: 0.14.34
3
+ Version: 0.14.36
4
4
  Summary:
5
5
  License: MIT
6
6
  Requires-Python: >=3.9,<4.0
@@ -7,7 +7,7 @@ vellum_cli/image_push.py,sha256=8DDvRDJEZ-FukUCqGW1827bg1ybF4xBbx9WyqWYQE-g,6816
7
7
  vellum_cli/init.py,sha256=WpnMXPItPmh0f0bBGIer3p-e5gu8DUGwSArT_FuoMEw,5093
8
8
  vellum_cli/logger.py,sha256=PuRFa0WCh4sAGFS5aqWB0QIYpS6nBWwPJrIXpWxugV4,1022
9
9
  vellum_cli/ping.py,sha256=p_BCCRjgPhng6JktuECtkDQLbhopt6JpmrtGoLnLJT8,1161
10
- vellum_cli/pull.py,sha256=YTo5cVCcp7RjS9lHednOuud4rW4bH7jqV3GMdbic_Uk,12002
10
+ vellum_cli/pull.py,sha256=27Mh10aQ8H1OkTmQOJcOuJ5cQcYbNjkkuQrBmtkRe0o,12262
11
11
  vellum_cli/push.py,sha256=xjTNbLwOVFNU3kpBrm56Bk5QkSRrJ9z86qceghCzfIA,9655
12
12
  vellum_cli/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  vellum_cli/tests/conftest.py,sha256=AFYZryKA2qnUuCPBxBKmHLFoPiE0WhBFFej9tNwSHdc,1526
@@ -16,7 +16,7 @@ vellum_cli/tests/test_image_push.py,sha256=i3lJuW8nFRwL1M1OF6752IZYvGAFgKmkB2hd_
16
16
  vellum_cli/tests/test_init.py,sha256=8UOc_ThfouR4ja5cCl_URuLk7ohr9JXfCnG4yka1OUQ,18754
17
17
  vellum_cli/tests/test_main.py,sha256=qDZG-aQauPwBwM6A2DIu1494n47v3pL28XakTbLGZ-k,272
18
18
  vellum_cli/tests/test_ping.py,sha256=3ucVRThEmTadlV9LrJdCCrr1Ofj3rOjG6ue0BNR2UC0,2523
19
- vellum_cli/tests/test_pull.py,sha256=fci5idbcAsnvfJcmP8KlULX4w4gkjLtXkn3iV4wsLZA,46472
19
+ vellum_cli/tests/test_pull.py,sha256=5nIDX5yXLyi6p-siLvrzfaepI4RWbaoMwgFoQFUEhI0,46692
20
20
  vellum_cli/tests/test_push.py,sha256=zDv_Q1hbXtLwmTJDPRAvwDjbuHC09uNRYOy4FQujUow,23476
21
21
  vellum_ee/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  vellum_ee/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -123,12 +123,12 @@ vellum_ee/workflows/tests/local_workflow/workflow.py,sha256=A4qOzOPNwePYxWbcAgIP
123
123
  vellum_ee/workflows/tests/test_display_meta.py,sha256=C25dErwghPNXio49pvSRxyOuc96srH6eYEwTAWdE2zY,2258
124
124
  vellum_ee/workflows/tests/test_server.py,sha256=SsOkS6sGO7uGC4mxvk4iv8AtcXs058P9hgFHzTWmpII,14519
125
125
  vellum_ee/workflows/tests/test_virtual_files.py,sha256=TJEcMR0v2S8CkloXNmCHA0QW0K6pYNGaIjraJz7sFvY,2762
126
- vellum/__init__.py,sha256=Ur02Hk_LtwXW45f-LBBtBhRX1xJRSq05ytaQUfgIGmc,40970
126
+ vellum/__init__.py,sha256=hl6RSGwdQetF5BV0k-8eGbGDVhdnZDpYX7MQXpZ4c-0,41308
127
127
  vellum/client/README.md,sha256=JkCJjmMZl4jrPj46pkmL9dpK4gSzQQmP5I7z4aME4LY,4749
128
- vellum/client/__init__.py,sha256=ki-TDOmYzC0FePN7swDyE6UpHFQV_4dK7lqy4h-3s1Y,118148
128
+ vellum/client/__init__.py,sha256=Z-JHK2jGxhtTtmkLeOaUGGJWIUNYGNVBLvUewC6lp6w,118148
129
129
  vellum/client/core/__init__.py,sha256=SQ85PF84B9MuKnBwHNHWemSGuy-g_515gFYNFhvEE0I,1438
130
130
  vellum/client/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
131
- vellum/client/core/client_wrapper.py,sha256=-wKm98fWVAP4wszQZhj8UDobt3IotWN6IYciYhNcNck,1869
131
+ vellum/client/core/client_wrapper.py,sha256=xLCZEpnqwYGxZRQKKBufqucpuc1GH4onEtUKV7qvzdM,1869
132
132
  vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
133
133
  vellum/client/core/file.py,sha256=X9IbmkZmB2bB_DpmZAO3crWdXagOakAyn6UCOCImCPg,2322
134
134
  vellum/client/core/http_client.py,sha256=R0pQpCppnEtxccGvXl4uJ76s7ro_65Fo_erlNNLp_AI,19228
@@ -173,7 +173,7 @@ vellum/client/resources/organizations/client.py,sha256=Uye92moqjAcOCs4astmuFpT92
173
173
  vellum/client/resources/prompts/__init__.py,sha256=FTtvy8EDg9nNNg9WCatVgKTRYV8-_v1roeGPAKoa_pw,65
174
174
  vellum/client/resources/prompts/client.py,sha256=_rNTUjhl_ZF3vyQa_M1BSTrX4DlFXU_SXkwwCEYKD2s,6598
175
175
  vellum/client/resources/release_reviews/__init__.py,sha256=FTtvy8EDg9nNNg9WCatVgKTRYV8-_v1roeGPAKoa_pw,65
176
- vellum/client/resources/release_reviews/client.py,sha256=6u7qYK_fpRZzizYnFtUS06Q41RqEzSsre6RQwRimf8w,5088
176
+ vellum/client/resources/release_reviews/client.py,sha256=VLXcmw1o8cYYtdTJQpajJWE2ve1z40_IXIbQRQIhqpY,9395
177
177
  vellum/client/resources/sandboxes/__init__.py,sha256=FTtvy8EDg9nNNg9WCatVgKTRYV8-_v1roeGPAKoa_pw,65
178
178
  vellum/client/resources/sandboxes/client.py,sha256=SG4BV0NG1Ow10mXSu52ybj-c6hR7wcNxfGJK4eiHu_8,17670
179
179
  vellum/client/resources/test_suite_runs/__init__.py,sha256=FTtvy8EDg9nNNg9WCatVgKTRYV8-_v1roeGPAKoa_pw,65
@@ -195,7 +195,7 @@ vellum/client/resources/workspace_secrets/__init__.py,sha256=FTtvy8EDg9nNNg9WCat
195
195
  vellum/client/resources/workspace_secrets/client.py,sha256=h7UzXLyTttPq1t-JZGMg1BWxypxJvBGUdqg7KGT7MK4,8027
196
196
  vellum/client/resources/workspaces/__init__.py,sha256=FTtvy8EDg9nNNg9WCatVgKTRYV8-_v1roeGPAKoa_pw,65
197
197
  vellum/client/resources/workspaces/client.py,sha256=RthwzN1o-Jxwg5yyNNodavFyNUSxfLoTv26w3mRR5g8,3595
198
- vellum/client/types/__init__.py,sha256=ZGqDXdE0b5IdJIYVcPEUZ33lgiV5Jy47KM1c5OzyDok,61976
198
+ vellum/client/types/__init__.py,sha256=vfEaeh8-2xzhzeFo8j-OnbmezsjCd4EJS4zhxuw_JbE,62505
199
199
  vellum/client/types/ad_hoc_execute_prompt_event.py,sha256=bCjujA2XsOgyF3bRZbcEqV2rOIymRgsLoIRtZpB14xg,607
200
200
  vellum/client/types/ad_hoc_expand_meta.py,sha256=1gv-NCsy_6xBYupLvZH979yf2VMdxAU-l0y0ynMKZaw,1331
201
201
  vellum/client/types/ad_hoc_fulfilled_prompt_execution_meta.py,sha256=Bfvf1d_dkmshxRACVM5vcxbH_7AQY23RmrrnPc0ytYY,939
@@ -492,6 +492,9 @@ vellum/client/types/prompt_block_state.py,sha256=BRAzTYARoSU36IVZGWMeeqhl5fgFMXC
492
492
  vellum/client/types/prompt_deployment_expand_meta_request.py,sha256=agsiAaHB6lDoZPlnfJ2nmhB4Ud4EiJJTX05YmduyCPo,1910
493
493
  vellum/client/types/prompt_deployment_input_request.py,sha256=KrT4-Ew2VvTWXEkYQz2oyHn5EDOgrMW7FzRFaPH3ARg,353
494
494
  vellum/client/types/prompt_deployment_parent_context.py,sha256=eu8dYmRb789uZeFVzbRkJrErDYZXo35f2qaNBcY0wOQ,2319
495
+ vellum/client/types/prompt_deployment_release.py,sha256=H6sluuxANsoaX6gA9lw76lJkTECuxFofSeetKF00ze0,1346
496
+ vellum/client/types/prompt_deployment_release_prompt_deployment.py,sha256=tj8g0qEJyAuijxRBUV6nO2IITEorqVY-C37oqiWg6Po,582
497
+ vellum/client/types/prompt_deployment_release_prompt_version.py,sha256=NELGH68M8-SFtdci1Ygg0FpgjYeZgmBjfFke2m3GP8Y,577
495
498
  vellum/client/types/prompt_exec_config.py,sha256=kthvyEe-IzfTpOBd1fYrczHuxD-v7k6cwjmuaY170RQ,1390
496
499
  vellum/client/types/prompt_execution_meta.py,sha256=3hhMZgdAR5mKfnh2e_eVN3oKfT0E9w26khVPrpjn7jk,1141
497
500
  vellum/client/types/prompt_node_execution_meta.py,sha256=IyWH__nCp5uwS0N32b2ZEsA-Fv7AZDB4nnlRZayU2Gc,888
@@ -698,7 +701,8 @@ vellum/client/types/workflow_deployment_event_executions_response.py,sha256=x7mZ
698
701
  vellum/client/types/workflow_deployment_history_item.py,sha256=4WUPzcthBvEZ7iaisKfEg0soUtHjcTEnL_VUVaKpTyw,1420
699
702
  vellum/client/types/workflow_deployment_parent_context.py,sha256=QNyPj2o-jauaC48KrRjCWan1IKIbDgyuxLxURmhXsXM,2347
700
703
  vellum/client/types/workflow_deployment_read.py,sha256=tp1WaojTVE_dz1oiZ97h8ixMbIWDgy2yRu08A7wPMpw,2363
701
- vellum/client/types/workflow_deployment_release.py,sha256=UshzYZE5Fv1hAwztaMTD1Fs0JNQqbeNus0IrwXLkKL0,1444
704
+ vellum/client/types/workflow_deployment_release.py,sha256=1OveujSLRID7B6aGGjqsN5R8MbEHn3SS0sp3dj22DQs,1609
705
+ vellum/client/types/workflow_deployment_release_workflow_deployment.py,sha256=irWt901SImKChLayz7_52C1W7JldKiQHweqkjuMUoNQ,586
702
706
  vellum/client/types/workflow_deployment_release_workflow_version.py,sha256=NP3FoxLpgMUIK1OAPf_ei58mxE9F7BLAuw7q55CIcT8,989
703
707
  vellum/client/types/workflow_error.py,sha256=EQajkEmLS64T0wYm0goHQl0rT7Lguurk8pLwkhjsgAI,282
704
708
  vellum/client/types/workflow_event_display_context.py,sha256=tnO9lgIJKnLtuS6xum_QilI83LjOmnWCLtnSHLn1oNo,929
@@ -1157,6 +1161,9 @@ vellum/types/prompt_block_state.py,sha256=tKqNrZnHWjvfGS_6oIUTpdCPGxvRJa31Le6qWL
1157
1161
  vellum/types/prompt_deployment_expand_meta_request.py,sha256=5dBdvjjK9zCKxrPMdKQPj6iG8A06GAlb_zazde6qZsU,175
1158
1162
  vellum/types/prompt_deployment_input_request.py,sha256=z8CxCZWnKW8BBZajQ6iDnz-2gaxU-FrnYrVe_MvC3FU,169
1159
1163
  vellum/types/prompt_deployment_parent_context.py,sha256=U9X9PvXhG6ZUE8RxLrH13xfqKvs3DOwbxzWmujoXTbg,170
1164
+ vellum/types/prompt_deployment_release.py,sha256=jr4iRA0A6HaHbI1EINxUPLZrRCi6uKWOnvjxQZyu7bg,163
1165
+ vellum/types/prompt_deployment_release_prompt_deployment.py,sha256=WetrclgECqyJ6ppPp-dNaaHRt7ayawa9wszRBn3p2OE,181
1166
+ vellum/types/prompt_deployment_release_prompt_version.py,sha256=cFVyvBTHjiTSpA2SrFS_SkbB26UDigaBUSJmKh1SEkg,178
1160
1167
  vellum/types/prompt_exec_config.py,sha256=aNeOGDi6l2rVzvkFt8CJE6L3W2EmY8gZaSb5051w8as,156
1161
1168
  vellum/types/prompt_execution_meta.py,sha256=_5izDjusf-TM69zKhvXr5EHH4Fx9jfWkg8F5_KNJV-w,159
1162
1169
  vellum/types/prompt_node_execution_meta.py,sha256=cJoHlIn_lb_sLpQniB8eszRJvFI6mJij9QgUIiKtiCY,164
@@ -1364,6 +1371,7 @@ vellum/types/workflow_deployment_history_item.py,sha256=dp5pwzOVO83KPwAbYeO3NXlK
1364
1371
  vellum/types/workflow_deployment_parent_context.py,sha256=kB0eeRXagHqRnuDVA9B8aDlvBZVOmQ702JYXD8evh24,172
1365
1372
  vellum/types/workflow_deployment_read.py,sha256=dDGG27VP0bvC565JzeSOHJ-5Pvs7eCF4R8F9k8316bo,162
1366
1373
  vellum/types/workflow_deployment_release.py,sha256=lBnOc5Tw2-jLGWmthzkwdaLGvylcDiarO-maZSote0A,165
1374
+ vellum/types/workflow_deployment_release_workflow_deployment.py,sha256=8qT32r--NyJppqBizD9QP6jvM5YdcsdpGEtaKMG1RbE,185
1367
1375
  vellum/types/workflow_deployment_release_workflow_version.py,sha256=l5SJrY9z3lG5K82V2wY2sY50V40CQWKl95nDjnHu4Dc,182
1368
1376
  vellum/types/workflow_error.py,sha256=7rZcYJG5jYr4IbEvgv57G6Lxutrdg43SD8mUerd58_A,152
1369
1377
  vellum/types/workflow_event_display_context.py,sha256=jiH4vHlWYdT_2zM8yxPox3fXjnFStzIO46N90B2TdNA,168
@@ -1577,8 +1585,8 @@ vellum/workflows/nodes/displayable/final_output_node/node.py,sha256=PuQ0RvtAmoSI
1577
1585
  vellum/workflows/nodes/displayable/final_output_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1578
1586
  vellum/workflows/nodes/displayable/final_output_node/tests/test_node.py,sha256=E6LQ74qZjY4Xi4avx2qdOCgGhF8pEcNLBh8cqYRkzMI,709
1579
1587
  vellum/workflows/nodes/displayable/guardrail_node/__init__.py,sha256=Ab5eXmOoBhyV4dMWdzh32HLUmnPIBEK_zFCT38C4Fng,68
1580
- vellum/workflows/nodes/displayable/guardrail_node/node.py,sha256=A9_vuahgKSemPAZdrDJilWwciLhOBTcxINXRnUHQl_g,4427
1581
- vellum/workflows/nodes/displayable/guardrail_node/test_node.py,sha256=1yPIAt4_GWiUKT6u3rTW2XKp62b8xG8Jj3JWeCm5ZDM,1368
1588
+ vellum/workflows/nodes/displayable/guardrail_node/node.py,sha256=AHyqBiP9_XZx9jI-EbPY2dHDRwKrpo_SS6DAdrPBulA,5086
1589
+ vellum/workflows/nodes/displayable/guardrail_node/test_node.py,sha256=gpaa7fmVPLH2dDjlNTbjutF3SBXa_aearI3xYvZ4ekg,3533
1582
1590
  vellum/workflows/nodes/displayable/inline_prompt_node/__init__.py,sha256=gSUOoEZLlrx35-tQhSAd3An8WDwBqyiQh-sIebLU9wU,74
1583
1591
  vellum/workflows/nodes/displayable/inline_prompt_node/node.py,sha256=8RXZqWMzViUjFfbpmcy1gkSsKnEpci8BGwsuPYv4xMQ,3380
1584
1592
  vellum/workflows/nodes/displayable/inline_prompt_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -1588,9 +1596,9 @@ vellum/workflows/nodes/displayable/merge_node/node.py,sha256=nZtGGVAvY4fvGg8vwV6
1588
1596
  vellum/workflows/nodes/displayable/note_node/__init__.py,sha256=KWA3P4fyYJ-fOTky8qNGlcOotQ-HeHJ9AjZt6mRQmCE,58
1589
1597
  vellum/workflows/nodes/displayable/note_node/node.py,sha256=sIN1VBQ7zeT3GhN0kupXbFfdpvgedWV79k4woJNp5IQ,394
1590
1598
  vellum/workflows/nodes/displayable/prompt_deployment_node/__init__.py,sha256=krX1Hds-TSVYZsx0wJFX4wsAKkEFYOX1ifwRGiIM-EA,82
1591
- vellum/workflows/nodes/displayable/prompt_deployment_node/node.py,sha256=pb-KbrnfTRL7mmNtVAMmiCiys8raXkl5Od7sIu682xU,2707
1599
+ vellum/workflows/nodes/displayable/prompt_deployment_node/node.py,sha256=eUiQYdqJTrWhVcUgGAPJYEnRk6S71Yrzu5-c-XcVFs4,3243
1592
1600
  vellum/workflows/nodes/displayable/prompt_deployment_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1593
- vellum/workflows/nodes/displayable/prompt_deployment_node/tests/test_node.py,sha256=mHSecwE8bcwduM5wNKwDTzlLeh7ECdEEuT86BDgByPY,5798
1601
+ vellum/workflows/nodes/displayable/prompt_deployment_node/tests/test_node.py,sha256=nOFiv2s8MyRf6c6aQxJPhN6a0mk1dFL2HI8Gkfc09sk,7288
1594
1602
  vellum/workflows/nodes/displayable/search_node/__init__.py,sha256=hpBpvbrDYf43DElRZFLzieSn8weXiwNiiNOJurERQbs,62
1595
1603
  vellum/workflows/nodes/displayable/search_node/node.py,sha256=_VHHuTNN4icZBgc7O5U9SVKrv1zgKipU72fOtxTyrQU,1453
1596
1604
  vellum/workflows/nodes/displayable/search_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -1637,12 +1645,12 @@ vellum/workflows/runner/__init__.py,sha256=i1iG5sAhtpdsrlvwgH6B-m49JsINkiWyPWs8v
1637
1645
  vellum/workflows/runner/runner.py,sha256=ww4fjZJBENkB5HJxdj92kTz7k_EyifCeAreupy5qIxs,31813
1638
1646
  vellum/workflows/sandbox.py,sha256=GVJzVjMuYzOBnSrboB0_6MMRZWBluAyQ2o7syeaeBd0,2235
1639
1647
  vellum/workflows/state/__init__.py,sha256=yUUdR-_Vl7UiixNDYQZ-GEM_kJI9dnOia75TtuNEsnE,60
1640
- vellum/workflows/state/base.py,sha256=Vkhneko3VlQrPsMLU1PYSzXU_W1u7_AraJsghiv5O-4,15512
1648
+ vellum/workflows/state/base.py,sha256=LOQ2UCnpVLWISryfJwbicFCrRmothJQ7OQGJElgKlvg,15675
1641
1649
  vellum/workflows/state/context.py,sha256=KOAI1wEGn8dGmhmAemJaf4SZbitP3jpIBcwKfznQaRE,3076
1642
1650
  vellum/workflows/state/encoder.py,sha256=TnOQojc5lTQ83g9QbpA4UCqShJvutmTMxbpKt-9gNe4,1911
1643
1651
  vellum/workflows/state/store.py,sha256=uVe-oN73KwGV6M6YLhwZMMUQhzTQomsVfVnb8V91gVo,1147
1644
1652
  vellum/workflows/state/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1645
- vellum/workflows/state/tests/test_state.py,sha256=jBynFR4m74Vn51DdmKBLkxb1loTy1CnJPtzPmdAFQUo,5159
1653
+ vellum/workflows/state/tests/test_state.py,sha256=m8f0jPTnK3i0W3wj5GTTRcetRrIBqBMklSA7Vev2nsg,6491
1646
1654
  vellum/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1647
1655
  vellum/workflows/tests/test_sandbox.py,sha256=JKwaluI-lODQo7Ek9sjDstjL_WTdSqUlVik6ZVTfVOA,1826
1648
1656
  vellum/workflows/tests/test_undefined.py,sha256=zMCVliCXVNLrlC6hEGyOWDnQADJ2g83yc5FIM33zuo8,353
@@ -1670,8 +1678,8 @@ vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnad
1670
1678
  vellum/workflows/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1671
1679
  vellum/workflows/workflows/tests/test_base_workflow.py,sha256=tCxrV3QBHL8wfdEO3bvKteDdw32xBlUl1_WxkAwaONw,8344
1672
1680
  vellum/workflows/workflows/tests/test_context.py,sha256=VJBUcyWVtMa_lE5KxdhgMu0WYNYnUQUDvTF7qm89hJ0,2333
1673
- vellum_ai-0.14.34.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1674
- vellum_ai-0.14.34.dist-info/METADATA,sha256=1DTJPYOhbXBtorWcrH9e992hHsfsTsvKtleo96NqcaY,5484
1675
- vellum_ai-0.14.34.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1676
- vellum_ai-0.14.34.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1677
- vellum_ai-0.14.34.dist-info/RECORD,,
1681
+ vellum_ai-0.14.36.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1682
+ vellum_ai-0.14.36.dist-info/METADATA,sha256=8nijTIGNJWT-D2j9VvMW7PARaKyi1lKH76DMnGPzXoY,5484
1683
+ vellum_ai-0.14.36.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1684
+ vellum_ai-0.14.36.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1685
+ vellum_ai-0.14.36.dist-info/RECORD,,
vellum_cli/pull.py CHANGED
@@ -35,6 +35,7 @@ class PullContentsMetadata(UniversalBaseModel):
35
35
  runner_config: Optional[RunnerConfig] = None
36
36
  deployment_id: Optional[UUID] = None
37
37
  deployment_name: Optional[str] = None
38
+ workflow_sandbox_id: Optional[UUID] = None
38
39
 
39
40
 
40
41
  def _resolve_workflow_config(
@@ -198,6 +199,8 @@ def pull_command(
198
199
  workflow_config.container_image_tag = pull_contents_metadata.runner_config.container_image_tag
199
200
  if workflow_config.container_image_name and not workflow_config.container_image_tag:
200
201
  workflow_config.container_image_tag = "latest"
202
+ if not workflow_config.workflow_sandbox_id and pull_contents_metadata.workflow_sandbox_id:
203
+ workflow_config.workflow_sandbox_id = str(pull_contents_metadata.workflow_sandbox_id)
201
204
  if not workflow_config.module and workflow_deployment and pull_contents_metadata.deployment_name:
202
205
  workflow_config.module = snake_case(pull_contents_metadata.deployment_name)
203
206
  if not workflow_config.module and pull_contents_metadata.label:
@@ -1185,7 +1185,7 @@ def test_pull__workflow_deployment_with_name_and_id(vellum_client):
1185
1185
  deployment_id = str(uuid4()) # config will always use the deployment_id return from the API
1186
1186
  deployment_name = "Test Deployment"
1187
1187
  deployment_label = "Test Label"
1188
-
1188
+ workflow_sandbox_id = str(uuid4())
1189
1189
  # AND the workflow pull API call returns a zip file with metadata
1190
1190
  vellum_client.workflows.pull.return_value = iter(
1191
1191
  [
@@ -1197,6 +1197,7 @@ def test_pull__workflow_deployment_with_name_and_id(vellum_client):
1197
1197
  "deployment_id": deployment_id,
1198
1198
  "deployment_name": deployment_name,
1199
1199
  "label": deployment_label,
1200
+ "workflow_sandbox_id": workflow_sandbox_id,
1200
1201
  }
1201
1202
  ),
1202
1203
  }
@@ -1227,6 +1228,7 @@ def test_pull__workflow_deployment_with_name_and_id(vellum_client):
1227
1228
  assert str(deployment["id"]) == deployment_id
1228
1229
  assert deployment["name"] == deployment_name
1229
1230
  assert deployment["label"] == deployment_label
1231
+ assert lock_data["workflows"][0]["workflow_sandbox_id"] == workflow_sandbox_id
1230
1232
 
1231
1233
  os.chdir(current_dir)
1232
1234
 
@@ -1248,6 +1250,7 @@ def test_pull__workflow_deployment_with_name_and_id(vellum_client):
1248
1250
  ]
1249
1251
  )
1250
1252
 
1253
+ os.chdir(temp_dir)
1251
1254
  result = runner.invoke(cli_main, ["workflows", "pull", "--workflow-deployment", deployment_name])
1252
1255
  assert result.exit_code == 0
1253
1256
  with open(vellum_lock_json) as f: