vellum-ai 0.13.21__py3-none-any.whl → 0.13.23__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 +12 -0
- vellum/client/__init__.py +170 -5
- vellum/client/core/client_wrapper.py +1 -1
- vellum/client/types/__init__.py +12 -0
- vellum/client/types/execute_api_request_bearer_token.py +6 -0
- vellum/client/types/execute_api_request_body.py +5 -0
- vellum/client/types/execute_api_request_headers_value.py +6 -0
- vellum/client/types/execute_api_response.py +24 -0
- vellum/client/types/method_enum.py +5 -0
- vellum/client/types/vellum_secret.py +19 -0
- vellum/plugins/pydantic.py +13 -1
- vellum/types/execute_api_request_bearer_token.py +3 -0
- vellum/types/execute_api_request_body.py +3 -0
- vellum/types/execute_api_request_headers_value.py +3 -0
- vellum/types/execute_api_response.py +3 -0
- vellum/types/method_enum.py +3 -0
- vellum/types/vellum_secret.py +3 -0
- vellum/workflows/nodes/core/inline_subworkflow_node/node.py +1 -0
- vellum/workflows/nodes/core/map_node/node.py +1 -0
- vellum/workflows/nodes/core/retry_node/node.py +1 -0
- vellum/workflows/nodes/core/try_node/node.py +11 -7
- vellum/workflows/nodes/displayable/api_node/node.py +12 -3
- vellum/workflows/nodes/displayable/api_node/tests/__init__.py +0 -0
- vellum/workflows/nodes/displayable/api_node/tests/test_api_node.py +34 -0
- vellum/workflows/nodes/displayable/bases/api_node/node.py +25 -4
- vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py +11 -3
- vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +27 -12
- vellum/workflows/nodes/displayable/code_execution_node/tests/test_code_execution_node.py +33 -0
- vellum/workflows/nodes/displayable/code_execution_node/utils.py +14 -12
- vellum/workflows/nodes/displayable/inline_prompt_node/tests/test_node.py +49 -0
- vellum/workflows/nodes/displayable/prompt_deployment_node/tests/__init__.py +0 -0
- vellum/workflows/nodes/displayable/prompt_deployment_node/tests/test_node.py +96 -0
- vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +29 -5
- vellum/workflows/nodes/displayable/subworkflow_deployment_node/tests/__init__.py +0 -0
- vellum/workflows/nodes/displayable/subworkflow_deployment_node/tests/test_node.py +131 -0
- vellum/workflows/nodes/mocks.py +17 -0
- vellum/workflows/runner/runner.py +14 -34
- vellum/workflows/state/context.py +29 -1
- vellum/workflows/workflows/base.py +9 -6
- {vellum_ai-0.13.21.dist-info → vellum_ai-0.13.23.dist-info}/METADATA +1 -1
- {vellum_ai-0.13.21.dist-info → vellum_ai-0.13.23.dist-info}/RECORD +50 -31
- vellum_cli/push.py +5 -6
- vellum_cli/tests/test_push.py +81 -1
- vellum_ee/workflows/display/types.py +1 -31
- vellum_ee/workflows/display/vellum.py +1 -1
- vellum_ee/workflows/display/workflows/base_workflow_display.py +46 -2
- vellum_ee/workflows/tests/test_server.py +9 -0
- vellum/workflows/types/cycle_map.py +0 -34
- {vellum_ai-0.13.21.dist-info → vellum_ai-0.13.23.dist-info}/LICENSE +0 -0
- {vellum_ai-0.13.21.dist-info → vellum_ai-0.13.23.dist-info}/WHEEL +0 -0
- {vellum_ai-0.13.21.dist-info → vellum_ai-0.13.23.dist-info}/entry_points.txt +0 -0
vellum/__init__.py
CHANGED
@@ -92,6 +92,10 @@ from .types import (
|
|
92
92
|
ErrorInput,
|
93
93
|
ErrorVellumValue,
|
94
94
|
ErrorVellumValueRequest,
|
95
|
+
ExecuteApiRequestBearerToken,
|
96
|
+
ExecuteApiRequestBody,
|
97
|
+
ExecuteApiRequestHeadersValue,
|
98
|
+
ExecuteApiResponse,
|
95
99
|
ExecutePromptEvent,
|
96
100
|
ExecutePromptResponse,
|
97
101
|
ExecuteWorkflowResponse,
|
@@ -183,6 +187,7 @@ from .types import (
|
|
183
187
|
MetadataFilterRuleCombinator,
|
184
188
|
MetadataFilterRuleRequest,
|
185
189
|
MetadataFiltersRequest,
|
190
|
+
MethodEnum,
|
186
191
|
MetricDefinitionExecution,
|
187
192
|
MetricDefinitionHistoryItem,
|
188
193
|
MetricDefinitionInput,
|
@@ -437,6 +442,7 @@ from .types import (
|
|
437
442
|
VellumErrorRequest,
|
438
443
|
VellumImage,
|
439
444
|
VellumImageRequest,
|
445
|
+
VellumSecret,
|
440
446
|
VellumValue,
|
441
447
|
VellumValueLogicalConditionGroupRequest,
|
442
448
|
VellumValueLogicalConditionRequest,
|
@@ -617,6 +623,10 @@ __all__ = [
|
|
617
623
|
"ErrorInput",
|
618
624
|
"ErrorVellumValue",
|
619
625
|
"ErrorVellumValueRequest",
|
626
|
+
"ExecuteApiRequestBearerToken",
|
627
|
+
"ExecuteApiRequestBody",
|
628
|
+
"ExecuteApiRequestHeadersValue",
|
629
|
+
"ExecuteApiResponse",
|
620
630
|
"ExecutePromptEvent",
|
621
631
|
"ExecutePromptResponse",
|
622
632
|
"ExecuteWorkflowResponse",
|
@@ -713,6 +723,7 @@ __all__ = [
|
|
713
723
|
"MetadataFilterRuleCombinator",
|
714
724
|
"MetadataFilterRuleRequest",
|
715
725
|
"MetadataFiltersRequest",
|
726
|
+
"MethodEnum",
|
716
727
|
"MetricDefinitionExecution",
|
717
728
|
"MetricDefinitionHistoryItem",
|
718
729
|
"MetricDefinitionInput",
|
@@ -970,6 +981,7 @@ __all__ = [
|
|
970
981
|
"VellumErrorRequest",
|
971
982
|
"VellumImage",
|
972
983
|
"VellumImageRequest",
|
984
|
+
"VellumSecret",
|
973
985
|
"VellumValue",
|
974
986
|
"VellumValueLogicalConditionGroupRequest",
|
975
987
|
"VellumValueLogicalConditionRequest",
|
vellum/client/__init__.py
CHANGED
@@ -21,17 +21,22 @@ from .resources.workflow_sandboxes.client import WorkflowSandboxesClient
|
|
21
21
|
from .resources.workflows.client import WorkflowsClient
|
22
22
|
from .resources.workspace_secrets.client import WorkspaceSecretsClient
|
23
23
|
from .resources.workspaces.client import WorkspacesClient
|
24
|
+
from .types.method_enum import MethodEnum
|
25
|
+
from .types.execute_api_request_body import ExecuteApiRequestBody
|
26
|
+
from .types.execute_api_request_headers_value import ExecuteApiRequestHeadersValue
|
27
|
+
from .types.execute_api_request_bearer_token import ExecuteApiRequestBearerToken
|
28
|
+
from .core.request_options import RequestOptions
|
29
|
+
from .types.execute_api_response import ExecuteApiResponse
|
30
|
+
from .core.serialization import convert_and_respect_annotation_metadata
|
31
|
+
from .core.pydantic_utilities import parse_obj_as
|
32
|
+
from json.decoder import JSONDecodeError
|
33
|
+
from .core.api_error import ApiError
|
24
34
|
from .types.code_execution_runtime import CodeExecutionRuntime
|
25
35
|
from .types.code_executor_input import CodeExecutorInput
|
26
36
|
from .types.code_execution_package import CodeExecutionPackage
|
27
37
|
from .types.vellum_variable_type import VellumVariableType
|
28
|
-
from .core.request_options import RequestOptions
|
29
38
|
from .types.code_executor_response import CodeExecutorResponse
|
30
|
-
from .core.serialization import convert_and_respect_annotation_metadata
|
31
|
-
from .core.pydantic_utilities import parse_obj_as
|
32
39
|
from .errors.bad_request_error import BadRequestError
|
33
|
-
from json.decoder import JSONDecodeError
|
34
|
-
from .core.api_error import ApiError
|
35
40
|
from .types.prompt_deployment_input_request import PromptDeploymentInputRequest
|
36
41
|
from .types.prompt_deployment_expand_meta_request import PromptDeploymentExpandMetaRequest
|
37
42
|
from .types.raw_prompt_execution_overrides_request import RawPromptExecutionOverridesRequest
|
@@ -149,6 +154,82 @@ class Vellum:
|
|
149
154
|
self.workspace_secrets = WorkspaceSecretsClient(client_wrapper=self._client_wrapper)
|
150
155
|
self.workspaces = WorkspacesClient(client_wrapper=self._client_wrapper)
|
151
156
|
|
157
|
+
def execute_api(
|
158
|
+
self,
|
159
|
+
*,
|
160
|
+
url: str,
|
161
|
+
method: typing.Optional[MethodEnum] = OMIT,
|
162
|
+
body: typing.Optional[ExecuteApiRequestBody] = OMIT,
|
163
|
+
headers: typing.Optional[typing.Dict[str, ExecuteApiRequestHeadersValue]] = OMIT,
|
164
|
+
bearer_token: typing.Optional[ExecuteApiRequestBearerToken] = OMIT,
|
165
|
+
request_options: typing.Optional[RequestOptions] = None,
|
166
|
+
) -> ExecuteApiResponse:
|
167
|
+
"""
|
168
|
+
Parameters
|
169
|
+
----------
|
170
|
+
url : str
|
171
|
+
|
172
|
+
method : typing.Optional[MethodEnum]
|
173
|
+
|
174
|
+
body : typing.Optional[ExecuteApiRequestBody]
|
175
|
+
|
176
|
+
headers : typing.Optional[typing.Dict[str, ExecuteApiRequestHeadersValue]]
|
177
|
+
|
178
|
+
bearer_token : typing.Optional[ExecuteApiRequestBearerToken]
|
179
|
+
|
180
|
+
request_options : typing.Optional[RequestOptions]
|
181
|
+
Request-specific configuration.
|
182
|
+
|
183
|
+
Returns
|
184
|
+
-------
|
185
|
+
ExecuteApiResponse
|
186
|
+
|
187
|
+
|
188
|
+
Examples
|
189
|
+
--------
|
190
|
+
from vellum import Vellum
|
191
|
+
|
192
|
+
client = Vellum(
|
193
|
+
api_key="YOUR_API_KEY",
|
194
|
+
)
|
195
|
+
client.execute_api(
|
196
|
+
url="url",
|
197
|
+
)
|
198
|
+
"""
|
199
|
+
_response = self._client_wrapper.httpx_client.request(
|
200
|
+
"v1/execute-api",
|
201
|
+
base_url=self._client_wrapper.get_environment().default,
|
202
|
+
method="POST",
|
203
|
+
json={
|
204
|
+
"url": url,
|
205
|
+
"method": method,
|
206
|
+
"body": convert_and_respect_annotation_metadata(
|
207
|
+
object_=body, annotation=ExecuteApiRequestBody, direction="write"
|
208
|
+
),
|
209
|
+
"headers": convert_and_respect_annotation_metadata(
|
210
|
+
object_=headers, annotation=typing.Dict[str, ExecuteApiRequestHeadersValue], direction="write"
|
211
|
+
),
|
212
|
+
"bearer_token": convert_and_respect_annotation_metadata(
|
213
|
+
object_=bearer_token, annotation=ExecuteApiRequestBearerToken, direction="write"
|
214
|
+
),
|
215
|
+
},
|
216
|
+
request_options=request_options,
|
217
|
+
omit=OMIT,
|
218
|
+
)
|
219
|
+
try:
|
220
|
+
if 200 <= _response.status_code < 300:
|
221
|
+
return typing.cast(
|
222
|
+
ExecuteApiResponse,
|
223
|
+
parse_obj_as(
|
224
|
+
type_=ExecuteApiResponse, # type: ignore
|
225
|
+
object_=_response.json(),
|
226
|
+
),
|
227
|
+
)
|
228
|
+
_response_json = _response.json()
|
229
|
+
except JSONDecodeError:
|
230
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
231
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
232
|
+
|
152
233
|
def execute_code(
|
153
234
|
self,
|
154
235
|
*,
|
@@ -1414,6 +1495,90 @@ class AsyncVellum:
|
|
1414
1495
|
self.workspace_secrets = AsyncWorkspaceSecretsClient(client_wrapper=self._client_wrapper)
|
1415
1496
|
self.workspaces = AsyncWorkspacesClient(client_wrapper=self._client_wrapper)
|
1416
1497
|
|
1498
|
+
async def execute_api(
|
1499
|
+
self,
|
1500
|
+
*,
|
1501
|
+
url: str,
|
1502
|
+
method: typing.Optional[MethodEnum] = OMIT,
|
1503
|
+
body: typing.Optional[ExecuteApiRequestBody] = OMIT,
|
1504
|
+
headers: typing.Optional[typing.Dict[str, ExecuteApiRequestHeadersValue]] = OMIT,
|
1505
|
+
bearer_token: typing.Optional[ExecuteApiRequestBearerToken] = OMIT,
|
1506
|
+
request_options: typing.Optional[RequestOptions] = None,
|
1507
|
+
) -> ExecuteApiResponse:
|
1508
|
+
"""
|
1509
|
+
Parameters
|
1510
|
+
----------
|
1511
|
+
url : str
|
1512
|
+
|
1513
|
+
method : typing.Optional[MethodEnum]
|
1514
|
+
|
1515
|
+
body : typing.Optional[ExecuteApiRequestBody]
|
1516
|
+
|
1517
|
+
headers : typing.Optional[typing.Dict[str, ExecuteApiRequestHeadersValue]]
|
1518
|
+
|
1519
|
+
bearer_token : typing.Optional[ExecuteApiRequestBearerToken]
|
1520
|
+
|
1521
|
+
request_options : typing.Optional[RequestOptions]
|
1522
|
+
Request-specific configuration.
|
1523
|
+
|
1524
|
+
Returns
|
1525
|
+
-------
|
1526
|
+
ExecuteApiResponse
|
1527
|
+
|
1528
|
+
|
1529
|
+
Examples
|
1530
|
+
--------
|
1531
|
+
import asyncio
|
1532
|
+
|
1533
|
+
from vellum import AsyncVellum
|
1534
|
+
|
1535
|
+
client = AsyncVellum(
|
1536
|
+
api_key="YOUR_API_KEY",
|
1537
|
+
)
|
1538
|
+
|
1539
|
+
|
1540
|
+
async def main() -> None:
|
1541
|
+
await client.execute_api(
|
1542
|
+
url="url",
|
1543
|
+
)
|
1544
|
+
|
1545
|
+
|
1546
|
+
asyncio.run(main())
|
1547
|
+
"""
|
1548
|
+
_response = await self._client_wrapper.httpx_client.request(
|
1549
|
+
"v1/execute-api",
|
1550
|
+
base_url=self._client_wrapper.get_environment().default,
|
1551
|
+
method="POST",
|
1552
|
+
json={
|
1553
|
+
"url": url,
|
1554
|
+
"method": method,
|
1555
|
+
"body": convert_and_respect_annotation_metadata(
|
1556
|
+
object_=body, annotation=ExecuteApiRequestBody, direction="write"
|
1557
|
+
),
|
1558
|
+
"headers": convert_and_respect_annotation_metadata(
|
1559
|
+
object_=headers, annotation=typing.Dict[str, ExecuteApiRequestHeadersValue], direction="write"
|
1560
|
+
),
|
1561
|
+
"bearer_token": convert_and_respect_annotation_metadata(
|
1562
|
+
object_=bearer_token, annotation=ExecuteApiRequestBearerToken, direction="write"
|
1563
|
+
),
|
1564
|
+
},
|
1565
|
+
request_options=request_options,
|
1566
|
+
omit=OMIT,
|
1567
|
+
)
|
1568
|
+
try:
|
1569
|
+
if 200 <= _response.status_code < 300:
|
1570
|
+
return typing.cast(
|
1571
|
+
ExecuteApiResponse,
|
1572
|
+
parse_obj_as(
|
1573
|
+
type_=ExecuteApiResponse, # type: ignore
|
1574
|
+
object_=_response.json(),
|
1575
|
+
),
|
1576
|
+
)
|
1577
|
+
_response_json = _response.json()
|
1578
|
+
except JSONDecodeError:
|
1579
|
+
raise ApiError(status_code=_response.status_code, body=_response.text)
|
1580
|
+
raise ApiError(status_code=_response.status_code, body=_response_json)
|
1581
|
+
|
1417
1582
|
async def execute_code(
|
1418
1583
|
self,
|
1419
1584
|
*,
|
@@ -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.
|
21
|
+
"X-Fern-SDK-Version": "0.13.23",
|
22
22
|
}
|
23
23
|
headers["X_API_KEY"] = self.api_key
|
24
24
|
return headers
|
vellum/client/types/__init__.py
CHANGED
@@ -96,6 +96,10 @@ from .ephemeral_prompt_cache_config_type_enum import EphemeralPromptCacheConfigT
|
|
96
96
|
from .error_input import ErrorInput
|
97
97
|
from .error_vellum_value import ErrorVellumValue
|
98
98
|
from .error_vellum_value_request import ErrorVellumValueRequest
|
99
|
+
from .execute_api_request_bearer_token import ExecuteApiRequestBearerToken
|
100
|
+
from .execute_api_request_body import ExecuteApiRequestBody
|
101
|
+
from .execute_api_request_headers_value import ExecuteApiRequestHeadersValue
|
102
|
+
from .execute_api_response import ExecuteApiResponse
|
99
103
|
from .execute_prompt_event import ExecutePromptEvent
|
100
104
|
from .execute_prompt_response import ExecutePromptResponse
|
101
105
|
from .execute_workflow_response import ExecuteWorkflowResponse
|
@@ -191,6 +195,7 @@ from .metadata_filter_config_request import MetadataFilterConfigRequest
|
|
191
195
|
from .metadata_filter_rule_combinator import MetadataFilterRuleCombinator
|
192
196
|
from .metadata_filter_rule_request import MetadataFilterRuleRequest
|
193
197
|
from .metadata_filters_request import MetadataFiltersRequest
|
198
|
+
from .method_enum import MethodEnum
|
194
199
|
from .metric_definition_execution import MetricDefinitionExecution
|
195
200
|
from .metric_definition_history_item import MetricDefinitionHistoryItem
|
196
201
|
from .metric_definition_input import MetricDefinitionInput
|
@@ -461,6 +466,7 @@ from .vellum_error_code_enum import VellumErrorCodeEnum
|
|
461
466
|
from .vellum_error_request import VellumErrorRequest
|
462
467
|
from .vellum_image import VellumImage
|
463
468
|
from .vellum_image_request import VellumImageRequest
|
469
|
+
from .vellum_secret import VellumSecret
|
464
470
|
from .vellum_value import VellumValue
|
465
471
|
from .vellum_value_logical_condition_group_request import VellumValueLogicalConditionGroupRequest
|
466
472
|
from .vellum_value_logical_condition_request import VellumValueLogicalConditionRequest
|
@@ -606,6 +612,10 @@ __all__ = [
|
|
606
612
|
"ErrorInput",
|
607
613
|
"ErrorVellumValue",
|
608
614
|
"ErrorVellumValueRequest",
|
615
|
+
"ExecuteApiRequestBearerToken",
|
616
|
+
"ExecuteApiRequestBody",
|
617
|
+
"ExecuteApiRequestHeadersValue",
|
618
|
+
"ExecuteApiResponse",
|
609
619
|
"ExecutePromptEvent",
|
610
620
|
"ExecutePromptResponse",
|
611
621
|
"ExecuteWorkflowResponse",
|
@@ -697,6 +707,7 @@ __all__ = [
|
|
697
707
|
"MetadataFilterRuleCombinator",
|
698
708
|
"MetadataFilterRuleRequest",
|
699
709
|
"MetadataFiltersRequest",
|
710
|
+
"MethodEnum",
|
700
711
|
"MetricDefinitionExecution",
|
701
712
|
"MetricDefinitionHistoryItem",
|
702
713
|
"MetricDefinitionInput",
|
@@ -951,6 +962,7 @@ __all__ = [
|
|
951
962
|
"VellumErrorRequest",
|
952
963
|
"VellumImage",
|
953
964
|
"VellumImageRequest",
|
965
|
+
"VellumSecret",
|
954
966
|
"VellumValue",
|
955
967
|
"VellumValueLogicalConditionGroupRequest",
|
956
968
|
"VellumValueLogicalConditionRequest",
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# This file was auto-generated by Fern from our API Definition.
|
2
|
+
|
3
|
+
from ..core.pydantic_utilities import UniversalBaseModel
|
4
|
+
import typing_extensions
|
5
|
+
import typing
|
6
|
+
from ..core.serialization import FieldMetadata
|
7
|
+
from ..core.pydantic_utilities import IS_PYDANTIC_V2
|
8
|
+
import pydantic
|
9
|
+
|
10
|
+
|
11
|
+
class ExecuteApiResponse(UniversalBaseModel):
|
12
|
+
status_code: int
|
13
|
+
text: str
|
14
|
+
json_: typing_extensions.Annotated[typing.Dict[str, typing.Optional[typing.Any]], FieldMetadata(alias="json")]
|
15
|
+
headers: typing.Dict[str, str]
|
16
|
+
|
17
|
+
if IS_PYDANTIC_V2:
|
18
|
+
model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
|
19
|
+
else:
|
20
|
+
|
21
|
+
class Config:
|
22
|
+
frozen = True
|
23
|
+
smart_union = True
|
24
|
+
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 VellumSecret(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
|
vellum/plugins/pydantic.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
from functools import lru_cache
|
2
2
|
from typing import Any, Dict, Literal, Optional, Tuple, Union
|
3
3
|
|
4
|
+
from pydantic.fields import FieldInfo
|
4
5
|
from pydantic.plugin import (
|
5
6
|
PydanticPluginProtocol,
|
6
7
|
SchemaKind,
|
@@ -39,11 +40,22 @@ class OnValidatePython(ValidatePythonHandlerProtocol):
|
|
39
40
|
if not isinstance(input, dict):
|
40
41
|
return
|
41
42
|
|
43
|
+
if self_instance:
|
44
|
+
model_fields: Dict[str, FieldInfo] = self_instance.model_fields
|
45
|
+
else:
|
46
|
+
model_fields = {}
|
47
|
+
|
42
48
|
self.tracked_descriptors = {}
|
43
49
|
BaseDescriptor = import_base_descriptor()
|
44
50
|
|
45
51
|
for key, value in input.items():
|
46
|
-
|
52
|
+
field_info = model_fields.get(key)
|
53
|
+
if isinstance(value, BaseDescriptor) and (
|
54
|
+
not field_info
|
55
|
+
or not field_info.annotation
|
56
|
+
or not isinstance(field_info.annotation, type)
|
57
|
+
or not issubclass(field_info.annotation, BaseDescriptor)
|
58
|
+
):
|
47
59
|
self.tracked_descriptors[key] = value
|
48
60
|
# TODO: This does not yet work for descriptors that map to more complex types
|
49
61
|
# https://app.shortcut.com/vellum/story/4636
|
@@ -78,6 +78,7 @@ class InlineSubworkflowNode(
|
|
78
78
|
subworkflow_stream = subworkflow.stream(
|
79
79
|
inputs=self._compile_subworkflow_inputs(),
|
80
80
|
event_filter=all_workflow_event_filter,
|
81
|
+
node_output_mocks=self._context._get_all_node_output_mocks(),
|
81
82
|
)
|
82
83
|
|
83
84
|
outputs: Optional[BaseOutputs] = None
|
@@ -152,6 +152,7 @@ class MapNode(BaseAdornmentNode[StateType], Generic[StateType, MapNodeItemType])
|
|
152
152
|
)
|
153
153
|
events = subworkflow.stream(
|
154
154
|
inputs=self.SubworkflowInputs(index=index, item=item, all_items=self.items),
|
155
|
+
node_output_mocks=self._context._get_all_node_output_mocks(),
|
155
156
|
event_filter=all_workflow_event_filter,
|
156
157
|
)
|
157
158
|
|
@@ -44,6 +44,7 @@ class RetryNode(BaseAdornmentNode[StateType], Generic[StateType]):
|
|
44
44
|
)
|
45
45
|
terminal_event = subworkflow.run(
|
46
46
|
inputs=self.SubworkflowInputs(attempt_number=attempt_number),
|
47
|
+
node_output_mocks=self._context._get_all_node_output_mocks(),
|
47
48
|
)
|
48
49
|
if terminal_event.name == "workflow.execution.fulfilled":
|
49
50
|
node_outputs = self.Outputs()
|
@@ -1,5 +1,6 @@
|
|
1
1
|
from typing import Callable, Generic, Iterator, Optional, Set, Type
|
2
2
|
|
3
|
+
from vellum.workflows.context import execution_context, get_parent_context
|
3
4
|
from vellum.workflows.errors.types import WorkflowError, WorkflowErrorCode
|
4
5
|
from vellum.workflows.exceptions import NodeException
|
5
6
|
from vellum.workflows.nodes.bases import BaseNode
|
@@ -26,13 +27,16 @@ class TryNode(BaseAdornmentNode[StateType], Generic[StateType]):
|
|
26
27
|
error: Optional[WorkflowError] = None
|
27
28
|
|
28
29
|
def run(self) -> Iterator[BaseOutput]:
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
parent_context = get_parent_context() or self._context.parent_context
|
31
|
+
with execution_context(parent_context=parent_context):
|
32
|
+
subworkflow = self.subworkflow(
|
33
|
+
parent_state=self.state,
|
34
|
+
context=WorkflowContext(vellum_client=self._context.vellum_client),
|
35
|
+
)
|
36
|
+
subworkflow_stream = subworkflow.stream(
|
37
|
+
event_filter=all_workflow_event_filter,
|
38
|
+
node_output_mocks=self._context._get_all_node_output_mocks(),
|
39
|
+
)
|
36
40
|
|
37
41
|
outputs: Optional[BaseOutputs] = None
|
38
42
|
exception: Optional[NodeException] = None
|
@@ -33,6 +33,7 @@ class APINode(BaseAPINode):
|
|
33
33
|
def run(self) -> BaseAPINode.Outputs:
|
34
34
|
headers = self.headers or {}
|
35
35
|
header_overrides = {}
|
36
|
+
bearer_token = None
|
36
37
|
|
37
38
|
if (
|
38
39
|
self.authorization_type == AuthorizationType.API_KEY
|
@@ -40,9 +41,17 @@ class APINode(BaseAPINode):
|
|
40
41
|
and self.api_key_header_value
|
41
42
|
):
|
42
43
|
header_overrides[self.api_key_header_key] = self.api_key_header_value
|
43
|
-
elif self.authorization_type == AuthorizationType.BEARER_TOKEN:
|
44
|
+
elif self.authorization_type == AuthorizationType.BEARER_TOKEN and isinstance(self.bearer_token_value, str):
|
44
45
|
header_overrides["Authorization"] = f"Bearer {self.bearer_token_value}"
|
45
|
-
|
46
|
+
elif self.authorization_type == AuthorizationType.BEARER_TOKEN and isinstance(
|
47
|
+
self.bearer_token_value, VellumSecret
|
48
|
+
):
|
49
|
+
bearer_token = self.bearer_token_value
|
46
50
|
return self._run(
|
47
|
-
method=self.method,
|
51
|
+
method=self.method,
|
52
|
+
url=self.url,
|
53
|
+
data=self.data or self.json,
|
54
|
+
json=self.json,
|
55
|
+
headers={**headers, **header_overrides},
|
56
|
+
bearer_token=bearer_token,
|
48
57
|
)
|
File without changes
|
@@ -0,0 +1,34 @@
|
|
1
|
+
from vellum import ExecuteApiResponse, VellumSecret as ClientVellumSecret
|
2
|
+
from vellum.workflows.constants import APIRequestMethod, AuthorizationType
|
3
|
+
from vellum.workflows.nodes import APINode
|
4
|
+
from vellum.workflows.state import BaseState
|
5
|
+
from vellum.workflows.types.core import VellumSecret
|
6
|
+
|
7
|
+
|
8
|
+
def test_run_workflow__secrets(vellum_client):
|
9
|
+
vellum_client.execute_api.return_value = ExecuteApiResponse(
|
10
|
+
status_code=200,
|
11
|
+
text='{"status": 200, "data": [1, 2, 3]}',
|
12
|
+
json_={"data": [1, 2, 3]},
|
13
|
+
headers={"X-Response-Header": "bar"},
|
14
|
+
)
|
15
|
+
|
16
|
+
class SimpleBaseAPINode(APINode):
|
17
|
+
method = APIRequestMethod.POST
|
18
|
+
authorization_type = AuthorizationType.BEARER_TOKEN
|
19
|
+
url = "https://api.vellum.ai"
|
20
|
+
body = {
|
21
|
+
"key": "value",
|
22
|
+
}
|
23
|
+
headers = {
|
24
|
+
"X-Test-Header": "foo",
|
25
|
+
}
|
26
|
+
bearer_token_value = VellumSecret(name="secret")
|
27
|
+
|
28
|
+
node = SimpleBaseAPINode(state=BaseState())
|
29
|
+
terminal = node.run()
|
30
|
+
|
31
|
+
assert vellum_client.execute_api.call_count == 1
|
32
|
+
bearer_token = vellum_client.execute_api.call_args.kwargs["bearer_token"]
|
33
|
+
assert bearer_token == ClientVellumSecret(name="secret")
|
34
|
+
assert terminal.headers == {"X-Response-Header": "bar"}
|
@@ -3,6 +3,7 @@ from typing import Any, Dict, Generic, Optional, Union
|
|
3
3
|
from requests import Request, RequestException, Session
|
4
4
|
from requests.exceptions import JSONDecodeError
|
5
5
|
|
6
|
+
from vellum.client.types.vellum_secret import VellumSecret as ClientVellumSecret
|
6
7
|
from vellum.workflows.constants import APIRequestMethod
|
7
8
|
from vellum.workflows.errors.types import WorkflowErrorCode
|
8
9
|
from vellum.workflows.exceptions import NodeException
|
@@ -45,29 +46,49 @@ class BaseAPINode(BaseNode, Generic[StateType]):
|
|
45
46
|
self,
|
46
47
|
method: APIRequestMethod,
|
47
48
|
url: str,
|
48
|
-
data: Optional[str] = None,
|
49
|
+
data: Optional[Union[str, Any]] = None,
|
49
50
|
json: Any = None,
|
50
51
|
headers: Any = None,
|
52
|
+
bearer_token: Optional[VellumSecret] = None,
|
51
53
|
) -> Outputs:
|
54
|
+
vellum_instance = False
|
55
|
+
for header in headers or {}:
|
56
|
+
if isinstance(headers[header], VellumSecret):
|
57
|
+
vellum_instance = True
|
58
|
+
if vellum_instance or bearer_token:
|
59
|
+
return self._vellum_execute_api(bearer_token, data, headers, method, url)
|
60
|
+
else:
|
61
|
+
return self._local_execute_api(data, headers, json, method, url)
|
62
|
+
|
63
|
+
def _local_execute_api(self, data, headers, json, method, url):
|
52
64
|
try:
|
53
65
|
prepped = Request(method=method.value, url=url, data=data, json=json, headers=headers).prepare()
|
54
66
|
except Exception as e:
|
55
67
|
raise NodeException(f"Failed to prepare HTTP request: {e}", code=WorkflowErrorCode.PROVIDER_ERROR)
|
56
|
-
|
57
68
|
try:
|
58
69
|
with Session() as session:
|
59
70
|
response = session.send(prepped)
|
60
71
|
except RequestException as e:
|
61
72
|
raise NodeException(f"HTTP request failed: {e}", code=WorkflowErrorCode.PROVIDER_ERROR)
|
62
|
-
|
63
73
|
try:
|
64
74
|
json = response.json()
|
65
75
|
except JSONDecodeError:
|
66
76
|
json = None
|
67
|
-
|
68
77
|
return self.Outputs(
|
69
78
|
json=json,
|
70
79
|
headers={header: value for header, value in response.headers.items()},
|
71
80
|
status_code=response.status_code,
|
72
81
|
text=response.text,
|
73
82
|
)
|
83
|
+
|
84
|
+
def _vellum_execute_api(self, bearer_token, data, headers, method, url):
|
85
|
+
client_vellum_secret = ClientVellumSecret(name=bearer_token.name) if bearer_token else None
|
86
|
+
vellum_response = self._context.vellum_client.execute_api(
|
87
|
+
url=url, method=method.value, body=data, headers=headers, bearer_token=client_vellum_secret
|
88
|
+
)
|
89
|
+
return self.Outputs(
|
90
|
+
json=vellum_response.json_,
|
91
|
+
headers={header: value for header, value in vellum_response.headers.items()},
|
92
|
+
status_code=vellum_response.status_code,
|
93
|
+
text=vellum_response.text,
|
94
|
+
)
|