vellum-ai 0.14.4__py3-none-any.whl → 0.14.6__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.
- vellum/__init__.py +6 -0
- vellum/client/__init__.py +8 -8
- vellum/client/core/client_wrapper.py +1 -1
- vellum/client/resources/__init__.py +2 -0
- vellum/client/resources/workflow_sandboxes/__init__.py +3 -0
- vellum/client/resources/workflow_sandboxes/client.py +146 -0
- vellum/client/resources/workflow_sandboxes/types/__init__.py +5 -0
- vellum/client/resources/workflow_sandboxes/types/list_workflow_sandbox_examples_request_tag.py +5 -0
- vellum/client/types/__init__.py +4 -0
- vellum/client/types/paginated_workflow_sandbox_example_list.py +23 -0
- vellum/client/types/workflow_sandbox_example.py +22 -0
- vellum/resources/workflow_sandboxes/types/__init__.py +3 -0
- vellum/resources/workflow_sandboxes/types/list_workflow_sandbox_examples_request_tag.py +3 -0
- vellum/types/paginated_workflow_sandbox_example_list.py +3 -0
- vellum/types/workflow_sandbox_example.py +3 -0
- vellum/workflows/context.py +8 -3
- vellum/workflows/nodes/displayable/code_execution_node/tests/test_code_execution_node.py +81 -1
- vellum/workflows/nodes/displayable/code_execution_node/utils.py +44 -20
- vellum/workflows/nodes/displayable/prompt_deployment_node/node.py +17 -10
- vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +12 -2
- vellum/workflows/nodes/displayable/subworkflow_deployment_node/tests/test_node.py +23 -0
- vellum/workflows/workflows/base.py +61 -53
- vellum/workflows/workflows/tests/test_base_workflow.py +47 -0
- vellum/workflows/workflows/tests/test_context.py +60 -0
- {vellum_ai-0.14.4.dist-info → vellum_ai-0.14.6.dist-info}/METADATA +1 -1
- {vellum_ai-0.14.4.dist-info → vellum_ai-0.14.6.dist-info}/RECORD +39 -29
- vellum_ee/workflows/display/nodes/vellum/__init__.py +2 -0
- vellum_ee/workflows/display/nodes/vellum/base_adornment_node.py +39 -0
- vellum_ee/workflows/display/nodes/vellum/map_node.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/retry_node.py +36 -4
- vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py +31 -0
- vellum_ee/workflows/display/nodes/vellum/try_node.py +43 -29
- vellum_ee/workflows/display/nodes/vellum/utils.py +8 -0
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +25 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +14 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py +19 -1
- {vellum_ai-0.14.4.dist-info → vellum_ai-0.14.6.dist-info}/LICENSE +0 -0
- {vellum_ai-0.14.4.dist-info → vellum_ai-0.14.6.dist-info}/WHEEL +0 -0
- {vellum_ai-0.14.4.dist-info → vellum_ai-0.14.6.dist-info}/entry_points.txt +0 -0
vellum/__init__.py
CHANGED
@@ -259,6 +259,7 @@ from .types import (
|
|
259
259
|
PaginatedTestSuiteRunExecutionList,
|
260
260
|
PaginatedTestSuiteTestCaseList,
|
261
261
|
PaginatedWorkflowReleaseTagReadList,
|
262
|
+
PaginatedWorkflowSandboxExampleList,
|
262
263
|
PdfSearchResultMetaSource,
|
263
264
|
PdfSearchResultMetaSourceRequest,
|
264
265
|
PlainTextPromptBlock,
|
@@ -495,6 +496,7 @@ from .types import (
|
|
495
496
|
WorkflowResultEventOutputDataNumber,
|
496
497
|
WorkflowResultEventOutputDataSearchResults,
|
497
498
|
WorkflowResultEventOutputDataString,
|
499
|
+
WorkflowSandboxExample,
|
498
500
|
WorkflowStreamEvent,
|
499
501
|
WorkspaceRead,
|
500
502
|
WorkspaceSecretRead,
|
@@ -506,6 +508,7 @@ from .resources import (
|
|
506
508
|
FolderEntitiesListRequestEntityStatus,
|
507
509
|
ListDeploymentReleaseTagsRequestSource,
|
508
510
|
ListWorkflowReleaseTagsRequestSource,
|
511
|
+
ListWorkflowSandboxExamplesRequestTag,
|
509
512
|
WorkflowDeploymentsListRequestStatus,
|
510
513
|
WorkflowsPullRequestFormat,
|
511
514
|
ad_hoc,
|
@@ -713,6 +716,7 @@ __all__ = [
|
|
713
716
|
"JsonVellumValueRequest",
|
714
717
|
"ListDeploymentReleaseTagsRequestSource",
|
715
718
|
"ListWorkflowReleaseTagsRequestSource",
|
719
|
+
"ListWorkflowSandboxExamplesRequestTag",
|
716
720
|
"LogicalOperator",
|
717
721
|
"LogprobsEnum",
|
718
722
|
"MapNodeResult",
|
@@ -796,6 +800,7 @@ __all__ = [
|
|
796
800
|
"PaginatedTestSuiteRunExecutionList",
|
797
801
|
"PaginatedTestSuiteTestCaseList",
|
798
802
|
"PaginatedWorkflowReleaseTagReadList",
|
803
|
+
"PaginatedWorkflowSandboxExampleList",
|
799
804
|
"PdfSearchResultMetaSource",
|
800
805
|
"PdfSearchResultMetaSourceRequest",
|
801
806
|
"PlainTextPromptBlock",
|
@@ -1035,6 +1040,7 @@ __all__ = [
|
|
1035
1040
|
"WorkflowResultEventOutputDataNumber",
|
1036
1041
|
"WorkflowResultEventOutputDataSearchResults",
|
1037
1042
|
"WorkflowResultEventOutputDataString",
|
1043
|
+
"WorkflowSandboxExample",
|
1038
1044
|
"WorkflowStreamEvent",
|
1039
1045
|
"WorkflowsPullRequestFormat",
|
1040
1046
|
"WorkspaceRead",
|
vellum/client/__init__.py
CHANGED
@@ -360,7 +360,7 @@ class Vellum:
|
|
360
360
|
Optionally specify a release tag if you want to pin to a specific release of the Prompt Deployment
|
361
361
|
|
362
362
|
external_id : typing.Optional[str]
|
363
|
-
Optionally include a unique identifier for tracking purposes. Must be unique within a given
|
363
|
+
Optionally include a unique identifier for tracking purposes. Must be unique within a given Workspace.
|
364
364
|
|
365
365
|
expand_meta : typing.Optional[PromptDeploymentExpandMetaRequest]
|
366
366
|
An optionally specified configuration used to opt in to including additional metadata about this prompt execution in the API response. Corresponding values will be returned under the `meta` key of the API response.
|
@@ -508,7 +508,7 @@ class Vellum:
|
|
508
508
|
Optionally specify a release tag if you want to pin to a specific release of the Prompt Deployment
|
509
509
|
|
510
510
|
external_id : typing.Optional[str]
|
511
|
-
Optionally include a unique identifier for tracking purposes. Must be unique within a given
|
511
|
+
Optionally include a unique identifier for tracking purposes. Must be unique within a given Workspace.
|
512
512
|
|
513
513
|
expand_meta : typing.Optional[PromptDeploymentExpandMetaRequest]
|
514
514
|
An optionally specified configuration used to opt in to including additional metadata about this prompt execution in the API response. Corresponding values will be returned under the `meta` key of the API response.
|
@@ -667,7 +667,7 @@ class Vellum:
|
|
667
667
|
Optionally specify a release tag if you want to pin to a specific release of the Workflow Deployment
|
668
668
|
|
669
669
|
external_id : typing.Optional[str]
|
670
|
-
Optionally include a unique identifier for tracking purposes. Must be unique
|
670
|
+
Optionally include a unique identifier for tracking purposes. Must be unique within a given Workspace.
|
671
671
|
|
672
672
|
metadata : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
|
673
673
|
Arbitrary JSON metadata associated with this request. Can be used to capture additional monitoring data such as user id, session id, etc. for future analysis.
|
@@ -794,7 +794,7 @@ class Vellum:
|
|
794
794
|
Optionally specify a release tag if you want to pin to a specific release of the Workflow Deployment
|
795
795
|
|
796
796
|
external_id : typing.Optional[str]
|
797
|
-
Optionally include a unique identifier for tracking purposes. Must be unique
|
797
|
+
Optionally include a unique identifier for tracking purposes. Must be unique within a given Workspace.
|
798
798
|
|
799
799
|
event_types : typing.Optional[typing.Sequence[WorkflowExecutionEventType]]
|
800
800
|
Optionally specify which events you want to receive. Defaults to only WORKFLOW events. Note that the schema of non-WORKFLOW events is unstable and should be used with caution.
|
@@ -1717,7 +1717,7 @@ class AsyncVellum:
|
|
1717
1717
|
Optionally specify a release tag if you want to pin to a specific release of the Prompt Deployment
|
1718
1718
|
|
1719
1719
|
external_id : typing.Optional[str]
|
1720
|
-
Optionally include a unique identifier for tracking purposes. Must be unique within a given
|
1720
|
+
Optionally include a unique identifier for tracking purposes. Must be unique within a given Workspace.
|
1721
1721
|
|
1722
1722
|
expand_meta : typing.Optional[PromptDeploymentExpandMetaRequest]
|
1723
1723
|
An optionally specified configuration used to opt in to including additional metadata about this prompt execution in the API response. Corresponding values will be returned under the `meta` key of the API response.
|
@@ -1873,7 +1873,7 @@ class AsyncVellum:
|
|
1873
1873
|
Optionally specify a release tag if you want to pin to a specific release of the Prompt Deployment
|
1874
1874
|
|
1875
1875
|
external_id : typing.Optional[str]
|
1876
|
-
Optionally include a unique identifier for tracking purposes. Must be unique within a given
|
1876
|
+
Optionally include a unique identifier for tracking purposes. Must be unique within a given Workspace.
|
1877
1877
|
|
1878
1878
|
expand_meta : typing.Optional[PromptDeploymentExpandMetaRequest]
|
1879
1879
|
An optionally specified configuration used to opt in to including additional metadata about this prompt execution in the API response. Corresponding values will be returned under the `meta` key of the API response.
|
@@ -2040,7 +2040,7 @@ class AsyncVellum:
|
|
2040
2040
|
Optionally specify a release tag if you want to pin to a specific release of the Workflow Deployment
|
2041
2041
|
|
2042
2042
|
external_id : typing.Optional[str]
|
2043
|
-
Optionally include a unique identifier for tracking purposes. Must be unique
|
2043
|
+
Optionally include a unique identifier for tracking purposes. Must be unique within a given Workspace.
|
2044
2044
|
|
2045
2045
|
metadata : typing.Optional[typing.Dict[str, typing.Optional[typing.Any]]]
|
2046
2046
|
Arbitrary JSON metadata associated with this request. Can be used to capture additional monitoring data such as user id, session id, etc. for future analysis.
|
@@ -2175,7 +2175,7 @@ class AsyncVellum:
|
|
2175
2175
|
Optionally specify a release tag if you want to pin to a specific release of the Workflow Deployment
|
2176
2176
|
|
2177
2177
|
external_id : typing.Optional[str]
|
2178
|
-
Optionally include a unique identifier for tracking purposes. Must be unique
|
2178
|
+
Optionally include a unique identifier for tracking purposes. Must be unique within a given Workspace.
|
2179
2179
|
|
2180
2180
|
event_types : typing.Optional[typing.Sequence[WorkflowExecutionEventType]]
|
2181
2181
|
Optionally specify which events you want to receive. Defaults to only WORKFLOW events. Note that the schema of non-WORKFLOW events is unstable and should be used with caution.
|
@@ -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.
|
21
|
+
"X-Fern-SDK-Version": "0.14.6",
|
22
22
|
}
|
23
23
|
headers["X_API_KEY"] = self.api_key
|
24
24
|
return headers
|
@@ -23,6 +23,7 @@ from .deployments import DeploymentsListRequestStatus, ListDeploymentReleaseTags
|
|
23
23
|
from .document_indexes import DocumentIndexesListRequestStatus
|
24
24
|
from .folder_entities import FolderEntitiesListRequestEntityStatus
|
25
25
|
from .workflow_deployments import ListWorkflowReleaseTagsRequestSource, WorkflowDeploymentsListRequestStatus
|
26
|
+
from .workflow_sandboxes import ListWorkflowSandboxExamplesRequestTag
|
26
27
|
from .workflows import WorkflowsPullRequestFormat
|
27
28
|
|
28
29
|
__all__ = [
|
@@ -31,6 +32,7 @@ __all__ = [
|
|
31
32
|
"FolderEntitiesListRequestEntityStatus",
|
32
33
|
"ListDeploymentReleaseTagsRequestSource",
|
33
34
|
"ListWorkflowReleaseTagsRequestSource",
|
35
|
+
"ListWorkflowSandboxExamplesRequestTag",
|
34
36
|
"WorkflowDeploymentsListRequestStatus",
|
35
37
|
"WorkflowsPullRequestFormat",
|
36
38
|
"ad_hoc",
|
@@ -8,6 +8,8 @@ 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.list_workflow_sandbox_examples_request_tag import ListWorkflowSandboxExamplesRequestTag
|
12
|
+
from ...types.paginated_workflow_sandbox_example_list import PaginatedWorkflowSandboxExampleList
|
11
13
|
from ...core.client_wrapper import AsyncClientWrapper
|
12
14
|
|
13
15
|
# this is used as the default value for optional parameters
|
@@ -97,6 +99,74 @@ class WorkflowSandboxesClient:
|
|
97
99
|
raise ApiError(status_code=_response.status_code, body=_response.text)
|
98
100
|
raise ApiError(status_code=_response.status_code, body=_response_json)
|
99
101
|
|
102
|
+
def list_workflow_sandbox_examples(
|
103
|
+
self,
|
104
|
+
*,
|
105
|
+
limit: typing.Optional[int] = None,
|
106
|
+
offset: typing.Optional[int] = None,
|
107
|
+
ordering: typing.Optional[str] = None,
|
108
|
+
tag: typing.Optional[ListWorkflowSandboxExamplesRequestTag] = None,
|
109
|
+
request_options: typing.Optional[RequestOptions] = None,
|
110
|
+
) -> PaginatedWorkflowSandboxExampleList:
|
111
|
+
"""
|
112
|
+
List Workflow Sandbox examples that were previously cloned into the User's Workspace
|
113
|
+
|
114
|
+
Parameters
|
115
|
+
----------
|
116
|
+
limit : typing.Optional[int]
|
117
|
+
Number of results to return per page.
|
118
|
+
|
119
|
+
offset : typing.Optional[int]
|
120
|
+
The initial index from which to return the results.
|
121
|
+
|
122
|
+
ordering : typing.Optional[str]
|
123
|
+
Which field to use when ordering the results.
|
124
|
+
|
125
|
+
tag : typing.Optional[ListWorkflowSandboxExamplesRequestTag]
|
126
|
+
|
127
|
+
request_options : typing.Optional[RequestOptions]
|
128
|
+
Request-specific configuration.
|
129
|
+
|
130
|
+
Returns
|
131
|
+
-------
|
132
|
+
PaginatedWorkflowSandboxExampleList
|
133
|
+
|
134
|
+
|
135
|
+
Examples
|
136
|
+
--------
|
137
|
+
from vellum import Vellum
|
138
|
+
|
139
|
+
client = Vellum(
|
140
|
+
api_key="YOUR_API_KEY",
|
141
|
+
)
|
142
|
+
client.workflow_sandboxes.list_workflow_sandbox_examples()
|
143
|
+
"""
|
144
|
+
_response = self._client_wrapper.httpx_client.request(
|
145
|
+
"v1/workflow-sandboxes/examples",
|
146
|
+
base_url=self._client_wrapper.get_environment().default,
|
147
|
+
method="GET",
|
148
|
+
params={
|
149
|
+
"limit": limit,
|
150
|
+
"offset": offset,
|
151
|
+
"ordering": ordering,
|
152
|
+
"tag": tag,
|
153
|
+
},
|
154
|
+
request_options=request_options,
|
155
|
+
)
|
156
|
+
try:
|
157
|
+
if 200 <= _response.status_code < 300:
|
158
|
+
return typing.cast(
|
159
|
+
PaginatedWorkflowSandboxExampleList,
|
160
|
+
parse_obj_as(
|
161
|
+
type_=PaginatedWorkflowSandboxExampleList, # type: ignore
|
162
|
+
object_=_response.json(),
|
163
|
+
),
|
164
|
+
)
|
165
|
+
_response_json = _response.json()
|
166
|
+
except JSONDecodeError:
|
167
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
168
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
169
|
+
|
100
170
|
|
101
171
|
class AsyncWorkflowSandboxesClient:
|
102
172
|
def __init__(self, *, client_wrapper: AsyncClientWrapper):
|
@@ -188,3 +258,79 @@ class AsyncWorkflowSandboxesClient:
|
|
188
258
|
except JSONDecodeError:
|
189
259
|
raise ApiError(status_code=_response.status_code, body=_response.text)
|
190
260
|
raise ApiError(status_code=_response.status_code, body=_response_json)
|
261
|
+
|
262
|
+
async def list_workflow_sandbox_examples(
|
263
|
+
self,
|
264
|
+
*,
|
265
|
+
limit: typing.Optional[int] = None,
|
266
|
+
offset: typing.Optional[int] = None,
|
267
|
+
ordering: typing.Optional[str] = None,
|
268
|
+
tag: typing.Optional[ListWorkflowSandboxExamplesRequestTag] = None,
|
269
|
+
request_options: typing.Optional[RequestOptions] = None,
|
270
|
+
) -> PaginatedWorkflowSandboxExampleList:
|
271
|
+
"""
|
272
|
+
List Workflow Sandbox examples that were previously cloned into the User's Workspace
|
273
|
+
|
274
|
+
Parameters
|
275
|
+
----------
|
276
|
+
limit : typing.Optional[int]
|
277
|
+
Number of results to return per page.
|
278
|
+
|
279
|
+
offset : typing.Optional[int]
|
280
|
+
The initial index from which to return the results.
|
281
|
+
|
282
|
+
ordering : typing.Optional[str]
|
283
|
+
Which field to use when ordering the results.
|
284
|
+
|
285
|
+
tag : typing.Optional[ListWorkflowSandboxExamplesRequestTag]
|
286
|
+
|
287
|
+
request_options : typing.Optional[RequestOptions]
|
288
|
+
Request-specific configuration.
|
289
|
+
|
290
|
+
Returns
|
291
|
+
-------
|
292
|
+
PaginatedWorkflowSandboxExampleList
|
293
|
+
|
294
|
+
|
295
|
+
Examples
|
296
|
+
--------
|
297
|
+
import asyncio
|
298
|
+
|
299
|
+
from vellum import AsyncVellum
|
300
|
+
|
301
|
+
client = AsyncVellum(
|
302
|
+
api_key="YOUR_API_KEY",
|
303
|
+
)
|
304
|
+
|
305
|
+
|
306
|
+
async def main() -> None:
|
307
|
+
await client.workflow_sandboxes.list_workflow_sandbox_examples()
|
308
|
+
|
309
|
+
|
310
|
+
asyncio.run(main())
|
311
|
+
"""
|
312
|
+
_response = await self._client_wrapper.httpx_client.request(
|
313
|
+
"v1/workflow-sandboxes/examples",
|
314
|
+
base_url=self._client_wrapper.get_environment().default,
|
315
|
+
method="GET",
|
316
|
+
params={
|
317
|
+
"limit": limit,
|
318
|
+
"offset": offset,
|
319
|
+
"ordering": ordering,
|
320
|
+
"tag": tag,
|
321
|
+
},
|
322
|
+
request_options=request_options,
|
323
|
+
)
|
324
|
+
try:
|
325
|
+
if 200 <= _response.status_code < 300:
|
326
|
+
return typing.cast(
|
327
|
+
PaginatedWorkflowSandboxExampleList,
|
328
|
+
parse_obj_as(
|
329
|
+
type_=PaginatedWorkflowSandboxExampleList, # type: ignore
|
330
|
+
object_=_response.json(),
|
331
|
+
),
|
332
|
+
)
|
333
|
+
_response_json = _response.json()
|
334
|
+
except JSONDecodeError:
|
335
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
336
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
vellum/client/types/__init__.py
CHANGED
@@ -267,6 +267,7 @@ from .paginated_slim_workflow_deployment_list import PaginatedSlimWorkflowDeploy
|
|
267
267
|
from .paginated_test_suite_run_execution_list import PaginatedTestSuiteRunExecutionList
|
268
268
|
from .paginated_test_suite_test_case_list import PaginatedTestSuiteTestCaseList
|
269
269
|
from .paginated_workflow_release_tag_read_list import PaginatedWorkflowReleaseTagReadList
|
270
|
+
from .paginated_workflow_sandbox_example_list import PaginatedWorkflowSandboxExampleList
|
270
271
|
from .pdf_search_result_meta_source import PdfSearchResultMetaSource
|
271
272
|
from .pdf_search_result_meta_source_request import PdfSearchResultMetaSourceRequest
|
272
273
|
from .plain_text_prompt_block import PlainTextPromptBlock
|
@@ -519,6 +520,7 @@ from .workflow_result_event_output_data_json import WorkflowResultEventOutputDat
|
|
519
520
|
from .workflow_result_event_output_data_number import WorkflowResultEventOutputDataNumber
|
520
521
|
from .workflow_result_event_output_data_search_results import WorkflowResultEventOutputDataSearchResults
|
521
522
|
from .workflow_result_event_output_data_string import WorkflowResultEventOutputDataString
|
523
|
+
from .workflow_sandbox_example import WorkflowSandboxExample
|
522
524
|
from .workflow_stream_event import WorkflowStreamEvent
|
523
525
|
from .workspace_read import WorkspaceRead
|
524
526
|
from .workspace_secret_read import WorkspaceSecretRead
|
@@ -779,6 +781,7 @@ __all__ = [
|
|
779
781
|
"PaginatedTestSuiteRunExecutionList",
|
780
782
|
"PaginatedTestSuiteTestCaseList",
|
781
783
|
"PaginatedWorkflowReleaseTagReadList",
|
784
|
+
"PaginatedWorkflowSandboxExampleList",
|
782
785
|
"PdfSearchResultMetaSource",
|
783
786
|
"PdfSearchResultMetaSourceRequest",
|
784
787
|
"PlainTextPromptBlock",
|
@@ -1015,6 +1018,7 @@ __all__ = [
|
|
1015
1018
|
"WorkflowResultEventOutputDataNumber",
|
1016
1019
|
"WorkflowResultEventOutputDataSearchResults",
|
1017
1020
|
"WorkflowResultEventOutputDataString",
|
1021
|
+
"WorkflowSandboxExample",
|
1018
1022
|
"WorkflowStreamEvent",
|
1019
1023
|
"WorkspaceRead",
|
1020
1024
|
"WorkspaceSecretRead",
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# This file was auto-generated by Fern from our API Definition.
|
2
|
+
|
3
|
+
from ..core.pydantic_utilities import UniversalBaseModel
|
4
|
+
import typing
|
5
|
+
from .workflow_sandbox_example import WorkflowSandboxExample
|
6
|
+
from ..core.pydantic_utilities import IS_PYDANTIC_V2
|
7
|
+
import pydantic
|
8
|
+
|
9
|
+
|
10
|
+
class PaginatedWorkflowSandboxExampleList(UniversalBaseModel):
|
11
|
+
count: typing.Optional[int] = None
|
12
|
+
next: typing.Optional[str] = None
|
13
|
+
previous: typing.Optional[str] = None
|
14
|
+
results: typing.Optional[typing.List[WorkflowSandboxExample]] = None
|
15
|
+
|
16
|
+
if IS_PYDANTIC_V2:
|
17
|
+
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
|
18
|
+
else:
|
19
|
+
|
20
|
+
class Config:
|
21
|
+
frozen = True
|
22
|
+
smart_union = True
|
23
|
+
extra = pydantic.Extra.allow
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# This file was auto-generated by Fern from our API Definition.
|
2
|
+
|
3
|
+
from ..core.pydantic_utilities import UniversalBaseModel
|
4
|
+
import typing
|
5
|
+
from ..core.pydantic_utilities import IS_PYDANTIC_V2
|
6
|
+
import pydantic
|
7
|
+
|
8
|
+
|
9
|
+
class WorkflowSandboxExample(UniversalBaseModel):
|
10
|
+
id: str
|
11
|
+
label: str
|
12
|
+
description: typing.Optional[str] = None
|
13
|
+
icon_name: typing.Optional[str] = None
|
14
|
+
|
15
|
+
if IS_PYDANTIC_V2:
|
16
|
+
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
|
17
|
+
else:
|
18
|
+
|
19
|
+
class Config:
|
20
|
+
frozen = True
|
21
|
+
smart_union = True
|
22
|
+
extra = pydantic.Extra.allow
|
vellum/workflows/context.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
from contextlib import contextmanager
|
2
2
|
import threading
|
3
|
+
from uuid import UUID
|
3
4
|
from typing import Iterator, Optional, cast
|
4
5
|
|
5
6
|
from vellum.client.core import UniversalBaseModel
|
@@ -8,6 +9,7 @@ from vellum.workflows.events.types import ParentContext
|
|
8
9
|
|
9
10
|
class ExecutionContext(UniversalBaseModel):
|
10
11
|
parent_context: Optional[ParentContext] = None
|
12
|
+
trace_id: Optional[UUID] = None
|
11
13
|
|
12
14
|
|
13
15
|
_CONTEXT_KEY = "_execution_context"
|
@@ -30,11 +32,14 @@ def get_parent_context() -> ParentContext:
|
|
30
32
|
|
31
33
|
|
32
34
|
@contextmanager
|
33
|
-
def execution_context(
|
35
|
+
def execution_context(
|
36
|
+
parent_context: Optional[ParentContext] = None, trace_id: Optional[UUID] = None
|
37
|
+
) -> Iterator[None]:
|
34
38
|
"""Context manager for handling execution context."""
|
35
39
|
prev_context = get_execution_context()
|
36
|
-
|
37
|
-
|
40
|
+
set_trace_id = prev_context.trace_id or trace_id
|
41
|
+
set_parent_context = parent_context or prev_context.parent_context
|
42
|
+
set_context = ExecutionContext(parent_context=set_parent_context, trace_id=set_trace_id)
|
38
43
|
try:
|
39
44
|
set_execution_context(set_context)
|
40
45
|
yield
|
@@ -1,12 +1,16 @@
|
|
1
1
|
import pytest
|
2
2
|
import os
|
3
|
-
from typing import Any, Union
|
3
|
+
from typing import Any, List, Union
|
4
|
+
|
5
|
+
from pydantic import BaseModel
|
4
6
|
|
5
7
|
from vellum import CodeExecutorResponse, NumberVellumValue, StringInput, StringVellumValue
|
8
|
+
from vellum.client.types.chat_message import ChatMessage
|
6
9
|
from vellum.client.types.code_execution_package import CodeExecutionPackage
|
7
10
|
from vellum.client.types.code_executor_secret_input import CodeExecutorSecretInput
|
8
11
|
from vellum.client.types.function_call import FunctionCall
|
9
12
|
from vellum.client.types.number_input import NumberInput
|
13
|
+
from vellum.client.types.string_chat_message_content import StringChatMessageContent
|
10
14
|
from vellum.workflows.errors import WorkflowErrorCode
|
11
15
|
from vellum.workflows.exceptions import NodeException
|
12
16
|
from vellum.workflows.inputs.base import BaseInputs
|
@@ -610,3 +614,79 @@ def main(arg1: list[bool]) -> int:
|
|
610
614
|
|
611
615
|
# AND the error should contain the execution error details
|
612
616
|
assert outputs == {"result": 3, "log": ""}
|
617
|
+
|
618
|
+
|
619
|
+
def test_run_node__union_output_type__pydantic_children():
|
620
|
+
# GIVEN a node that is a union type with a pydantic child
|
621
|
+
class OptionOne(BaseModel):
|
622
|
+
foo: str
|
623
|
+
|
624
|
+
class OptionTwo(BaseModel):
|
625
|
+
bar: int
|
626
|
+
|
627
|
+
class ExampleCodeExecutionNode(CodeExecutionNode[BaseState, Union[OptionOne, OptionTwo]]):
|
628
|
+
code = """\
|
629
|
+
def main():
|
630
|
+
return { "foo": "hello" }
|
631
|
+
"""
|
632
|
+
runtime = "PYTHON_3_11_6"
|
633
|
+
code_inputs = {}
|
634
|
+
|
635
|
+
# WHEN we run the node
|
636
|
+
node = ExampleCodeExecutionNode()
|
637
|
+
|
638
|
+
# THEN it should run successfully
|
639
|
+
outputs = node.run()
|
640
|
+
|
641
|
+
# AND the result should be the correct type
|
642
|
+
assert outputs == {"result": OptionOne(foo="hello"), "log": ""}
|
643
|
+
|
644
|
+
|
645
|
+
def test_run_node__union_output_type__miss():
|
646
|
+
# GIVEN a node that is a union type
|
647
|
+
class ExampleCodeExecutionNode(CodeExecutionNode[BaseState, Union[int, float]]):
|
648
|
+
code = """\
|
649
|
+
def main():
|
650
|
+
return "hello"
|
651
|
+
"""
|
652
|
+
runtime = "PYTHON_3_11_6"
|
653
|
+
code_inputs = {}
|
654
|
+
|
655
|
+
# WHEN we run the node
|
656
|
+
node = ExampleCodeExecutionNode()
|
657
|
+
|
658
|
+
# THEN it should raise a NodeException with the execution error
|
659
|
+
with pytest.raises(NodeException) as exc_info:
|
660
|
+
node.run()
|
661
|
+
|
662
|
+
# AND the error should contain the execution error details
|
663
|
+
assert exc_info.value.message == "Expected an output of type 'int | float', but received 'str'"
|
664
|
+
|
665
|
+
|
666
|
+
def test_run_node__chat_history_output_type():
|
667
|
+
# GIVEN a node that that has a chat history return type
|
668
|
+
class ExampleCodeExecutionNode(CodeExecutionNode[BaseState, List[ChatMessage]]):
|
669
|
+
code = """\
|
670
|
+
def main():
|
671
|
+
return [
|
672
|
+
{
|
673
|
+
"role": "USER",
|
674
|
+
"content": {
|
675
|
+
"type": "STRING",
|
676
|
+
"value": "Hello, world!",
|
677
|
+
}
|
678
|
+
}
|
679
|
+
]
|
680
|
+
"""
|
681
|
+
code_inputs = {}
|
682
|
+
runtime = "PYTHON_3_11_6"
|
683
|
+
|
684
|
+
# WHEN we run the node
|
685
|
+
node = ExampleCodeExecutionNode()
|
686
|
+
outputs = node.run()
|
687
|
+
|
688
|
+
# AND the error should contain the execution error details
|
689
|
+
assert outputs == {
|
690
|
+
"result": [ChatMessage(role="USER", content=StringChatMessageContent(value="Hello, world!"))],
|
691
|
+
"log": "",
|
692
|
+
}
|
@@ -67,6 +67,49 @@ def _clean_for_dict_wrapper(obj):
|
|
67
67
|
return obj
|
68
68
|
|
69
69
|
|
70
|
+
def _get_type_name(obj: Any) -> str:
|
71
|
+
if isinstance(obj, type):
|
72
|
+
return obj.__name__
|
73
|
+
|
74
|
+
if get_origin(obj) is Union:
|
75
|
+
children = [_get_type_name(child) for child in get_args(obj)]
|
76
|
+
return " | ".join(children)
|
77
|
+
|
78
|
+
return str(obj)
|
79
|
+
|
80
|
+
|
81
|
+
def _cast_to_output_type(result: Any, output_type: Any) -> Any:
|
82
|
+
is_valid_output_type = isinstance(output_type, type)
|
83
|
+
if get_origin(output_type) is Union:
|
84
|
+
allowed_types = get_args(output_type)
|
85
|
+
for allowed_type in allowed_types:
|
86
|
+
try:
|
87
|
+
return _cast_to_output_type(result, allowed_type)
|
88
|
+
except NodeException:
|
89
|
+
continue
|
90
|
+
elif get_origin(output_type) is list:
|
91
|
+
allowed_item_type = get_args(output_type)[0]
|
92
|
+
if isinstance(result, list):
|
93
|
+
return [_cast_to_output_type(item, allowed_item_type) for item in result]
|
94
|
+
elif is_valid_output_type and issubclass(output_type, BaseModel) and not isinstance(result, output_type):
|
95
|
+
try:
|
96
|
+
return output_type.model_validate(result)
|
97
|
+
except ValidationError as e:
|
98
|
+
raise NodeException(
|
99
|
+
code=WorkflowErrorCode.INVALID_OUTPUTS,
|
100
|
+
message=re.sub(r"\s+For further information visit [^\s]+", "", str(e)),
|
101
|
+
) from e
|
102
|
+
elif is_valid_output_type and isinstance(result, output_type):
|
103
|
+
return result
|
104
|
+
|
105
|
+
output_type_name = _get_type_name(output_type)
|
106
|
+
result_type_name = _get_type_name(type(result))
|
107
|
+
raise NodeException(
|
108
|
+
code=WorkflowErrorCode.INVALID_OUTPUTS,
|
109
|
+
message=f"Expected an output of type '{output_type_name}', but received '{result_type_name}'",
|
110
|
+
)
|
111
|
+
|
112
|
+
|
70
113
|
def run_code_inline(
|
71
114
|
code: str,
|
72
115
|
inputs: EntityInputsInterface,
|
@@ -112,25 +155,6 @@ __arg__out = main({", ".join(run_args)})
|
|
112
155
|
result = exec_globals["__arg__out"]
|
113
156
|
|
114
157
|
if output_type != Any:
|
115
|
-
|
116
|
-
allowed_types = get_args(output_type)
|
117
|
-
if not isinstance(result, allowed_types):
|
118
|
-
raise NodeException(
|
119
|
-
code=WorkflowErrorCode.INVALID_OUTPUTS,
|
120
|
-
message=f"Expected output to be in types {allowed_types}, but received '{type(result).__name__}'",
|
121
|
-
)
|
122
|
-
elif issubclass(output_type, BaseModel) and not isinstance(result, output_type):
|
123
|
-
try:
|
124
|
-
result = output_type.model_validate(result)
|
125
|
-
except ValidationError as e:
|
126
|
-
raise NodeException(
|
127
|
-
code=WorkflowErrorCode.INVALID_OUTPUTS,
|
128
|
-
message=re.sub(r"\s+For further information visit [^\s]+", "", str(e)),
|
129
|
-
) from e
|
130
|
-
elif not isinstance(result, output_type):
|
131
|
-
raise NodeException(
|
132
|
-
code=WorkflowErrorCode.INVALID_OUTPUTS,
|
133
|
-
message=f"Expected an output of type '{output_type.__name__}', but received '{type(result).__name__}'",
|
134
|
-
)
|
158
|
+
result = _cast_to_output_type(result, output_type)
|
135
159
|
|
136
160
|
return logs, result
|