vellum-ai 0.14.45__py3-none-any.whl → 0.14.46__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/client/core/client_wrapper.py +1 -1
- vellum/workflows/nodes/core/try_node/node.py +3 -6
- vellum/workflows/nodes/core/try_node/tests/test_node.py +0 -24
- vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +8 -14
- vellum/workflows/nodes/displayable/code_execution_node/tests/test_code_execution_node.py +62 -0
- vellum/workflows/nodes/displayable/code_execution_node/utils.py +3 -54
- vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py +5 -6
- vellum/workflows/nodes/utils.py +4 -0
- vellum/workflows/types/code_execution_node_wrappers.py +64 -0
- vellum/workflows/vellum_client.py +19 -7
- {vellum_ai-0.14.45.dist-info → vellum_ai-0.14.46.dist-info}/METADATA +1 -1
- {vellum_ai-0.14.45.dist-info → vellum_ai-0.14.46.dist-info}/RECORD +26 -25
- vellum_cli/config.py +7 -2
- vellum_cli/push.py +5 -1
- vellum_cli/tests/test_push.py +192 -8
- vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py +1 -5
- vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py +1 -5
- vellum_ee/workflows/display/types.py +3 -0
- vellum_ee/workflows/display/utils/expressions.py +1 -1
- vellum_ee/workflows/display/utils/vellum.py +1 -3
- vellum_ee/workflows/display/workflows/base_workflow_display.py +10 -0
- vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py +3 -0
- vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +53 -0
- {vellum_ai-0.14.45.dist-info → vellum_ai-0.14.46.dist-info}/LICENSE +0 -0
- {vellum_ai-0.14.45.dist-info → vellum_ai-0.14.46.dist-info}/WHEEL +0 -0
- {vellum_ai-0.14.45.dist-info → vellum_ai-0.14.46.dist-info}/entry_points.txt +0 -0
@@ -18,7 +18,7 @@ class BaseClientWrapper:
|
|
18
18
|
headers: typing.Dict[str, str] = {
|
19
19
|
"X-Fern-Language": "Python",
|
20
20
|
"X-Fern-SDK-Name": "vellum-ai",
|
21
|
-
"X-Fern-SDK-Version": "0.14.
|
21
|
+
"X-Fern-SDK-Version": "0.14.46",
|
22
22
|
}
|
23
23
|
headers["X-API-KEY"] = self.api_key
|
24
24
|
return headers
|
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Callable, Generic, Iterator, Optional, Set, Type
|
1
|
+
from typing import Callable, Generic, Iterator, Optional, Set, Type
|
2
2
|
|
3
3
|
from vellum.workflows.context import execution_context, get_parent_context
|
4
4
|
from vellum.workflows.errors.types import WorkflowError, WorkflowErrorCode
|
@@ -21,8 +21,7 @@ class TryNode(BaseAdornmentNode[StateType], Generic[StateType]):
|
|
21
21
|
subworkflow: Type["BaseWorkflow"] - The Subworkflow to execute
|
22
22
|
"""
|
23
23
|
|
24
|
-
|
25
|
-
on_error_code: Optional[Union[WorkflowErrorCode, str]] = None
|
24
|
+
on_error_code: Optional[WorkflowErrorCode] = None
|
26
25
|
|
27
26
|
class Outputs(BaseAdornmentNode.Outputs):
|
28
27
|
error: Optional[WorkflowError] = None
|
@@ -66,9 +65,7 @@ class TryNode(BaseAdornmentNode[StateType], Generic[StateType]):
|
|
66
65
|
message="Subworkflow unexpectedly paused within Try Node",
|
67
66
|
)
|
68
67
|
elif event.name == "workflow.execution.rejected":
|
69
|
-
|
70
|
-
event_error_code = event.error.code.value if isinstance(self.on_error_code, str) else event.error.code
|
71
|
-
if self.on_error_code and self.on_error_code != event_error_code:
|
68
|
+
if self.on_error_code and self.on_error_code != event.error.code:
|
72
69
|
exception = NodeException(
|
73
70
|
code=WorkflowErrorCode.INVALID_OUTPUTS,
|
74
71
|
message=f"""Unexpected rejection: {event.error.code.value}.
|
@@ -57,30 +57,6 @@ def test_try_node__retry_on_error_code__missed():
|
|
57
57
|
assert exc_info.value.code == WorkflowErrorCode.INVALID_OUTPUTS
|
58
58
|
|
59
59
|
|
60
|
-
def test_try_node__on_error_code__str():
|
61
|
-
# GIVEN a try node that is configured to catch PROVIDER_ERROR
|
62
|
-
@TryNode.wrap(on_error_code="PROVIDER_ERROR") # type: ignore
|
63
|
-
class TestNode(BaseNode):
|
64
|
-
class Outputs(BaseOutputs):
|
65
|
-
value: int
|
66
|
-
|
67
|
-
def run(self) -> Outputs:
|
68
|
-
raise NodeException(message="This will be caught", code=WorkflowErrorCode.PROVIDER_ERROR)
|
69
|
-
|
70
|
-
# WHEN the node is run and throws a PROVIDER_ERROR
|
71
|
-
node = TestNode(state=BaseState())
|
72
|
-
outputs = [o for o in node.run()]
|
73
|
-
|
74
|
-
# THEN the exception is caught
|
75
|
-
assert len(outputs) == 2
|
76
|
-
assert set(outputs) == {
|
77
|
-
BaseOutput(name="value"),
|
78
|
-
BaseOutput(
|
79
|
-
name="error", value=WorkflowError(message="This will be caught", code=WorkflowErrorCode.PROVIDER_ERROR)
|
80
|
-
),
|
81
|
-
}
|
82
|
-
|
83
|
-
|
84
60
|
def test_try_node__use_parent_inputs_and_state():
|
85
61
|
# GIVEN a parent workflow Inputs and State
|
86
62
|
class Inputs(BaseInputs):
|
@@ -15,7 +15,7 @@ from vellum import (
|
|
15
15
|
)
|
16
16
|
from vellum.client import ApiError, RequestOptions
|
17
17
|
from vellum.client.types.chat_message_request import ChatMessageRequest
|
18
|
-
from vellum.workflows.constants import LATEST_RELEASE_TAG
|
18
|
+
from vellum.workflows.constants import LATEST_RELEASE_TAG
|
19
19
|
from vellum.workflows.context import get_execution_context
|
20
20
|
from vellum.workflows.errors import WorkflowErrorCode
|
21
21
|
from vellum.workflows.errors.types import vellum_error_to_workflow_error
|
@@ -48,13 +48,13 @@ class BasePromptDeploymentNode(BasePromptNode, Generic[StateType]):
|
|
48
48
|
deployment: ClassVar[Union[UUID, str]]
|
49
49
|
|
50
50
|
release_tag: str = LATEST_RELEASE_TAG
|
51
|
-
external_id: Optional[str] =
|
51
|
+
external_id: Optional[str] = None
|
52
52
|
|
53
|
-
expand_meta: Optional[PromptDeploymentExpandMetaRequest] =
|
54
|
-
raw_overrides: Optional[RawPromptExecutionOverridesRequest] =
|
55
|
-
expand_raw: Optional[Sequence[str]] =
|
56
|
-
metadata: Optional[Dict[str, Optional[Any]]] =
|
57
|
-
ml_model_fallbacks: Optional[Sequence[str]] =
|
53
|
+
expand_meta: Optional[PromptDeploymentExpandMetaRequest] = None
|
54
|
+
raw_overrides: Optional[RawPromptExecutionOverridesRequest] = None
|
55
|
+
expand_raw: Optional[Sequence[str]] = None
|
56
|
+
metadata: Optional[Dict[str, Optional[Any]]] = None
|
57
|
+
ml_model_fallbacks: Optional[Sequence[str]] = None
|
58
58
|
|
59
59
|
class Trigger(BasePromptNode.Trigger):
|
60
60
|
merge_behavior = MergeBehavior.AWAIT_ANY
|
@@ -103,12 +103,7 @@ class BasePromptDeploymentNode(BasePromptNode, Generic[StateType]):
|
|
103
103
|
prompt_event_stream = self._get_prompt_event_stream()
|
104
104
|
next(prompt_event_stream)
|
105
105
|
except ApiError as e:
|
106
|
-
if
|
107
|
-
e.status_code
|
108
|
-
and e.status_code < 500
|
109
|
-
and self.ml_model_fallbacks is not OMIT
|
110
|
-
and self.ml_model_fallbacks is not None
|
111
|
-
):
|
106
|
+
if e.status_code and e.status_code < 500 and self.ml_model_fallbacks is not None:
|
112
107
|
prompt_event_stream = self._retry_prompt_stream_with_fallbacks(tried_fallbacks)
|
113
108
|
else:
|
114
109
|
self._handle_api_error(e)
|
@@ -127,7 +122,6 @@ class BasePromptDeploymentNode(BasePromptNode, Generic[StateType]):
|
|
127
122
|
if (
|
128
123
|
event.error
|
129
124
|
and event.error.code == WorkflowErrorCode.PROVIDER_ERROR.value
|
130
|
-
and self.ml_model_fallbacks is not OMIT
|
131
125
|
and self.ml_model_fallbacks is not None
|
132
126
|
):
|
133
127
|
try:
|
@@ -821,3 +821,65 @@ def main(arg1: list) -> str:
|
|
821
821
|
|
822
822
|
# AND the result should be the correct output
|
823
823
|
assert outputs == {"result": "bar", "log": ""}
|
824
|
+
|
825
|
+
|
826
|
+
def test_run_node__string_value_wrapper__get_attr():
|
827
|
+
# GIVEN a node that accesses the 'value' property of a string input
|
828
|
+
class ExampleCodeExecutionNode(CodeExecutionNode[BaseState, str]):
|
829
|
+
code = """\
|
830
|
+
def main(text: str) -> str:
|
831
|
+
return text.value
|
832
|
+
"""
|
833
|
+
code_inputs = {
|
834
|
+
"text": "hello",
|
835
|
+
}
|
836
|
+
runtime = "PYTHON_3_11_6"
|
837
|
+
|
838
|
+
# WHEN we run the node
|
839
|
+
node = ExampleCodeExecutionNode()
|
840
|
+
outputs = node.run()
|
841
|
+
|
842
|
+
# THEN the node should successfully access the string value through the .value property
|
843
|
+
assert outputs == {"result": "hello", "log": ""}
|
844
|
+
|
845
|
+
|
846
|
+
def test_run_node__string_value_wrapper__get_item():
|
847
|
+
# GIVEN a node that accesses the 'value' property of a string input
|
848
|
+
class ExampleCodeExecutionNode(CodeExecutionNode[BaseState, str]):
|
849
|
+
code = """\
|
850
|
+
def main(text: str) -> str:
|
851
|
+
return text["value"]
|
852
|
+
"""
|
853
|
+
code_inputs = {
|
854
|
+
"text": "hello",
|
855
|
+
}
|
856
|
+
runtime = "PYTHON_3_11_6"
|
857
|
+
|
858
|
+
# WHEN we run the node
|
859
|
+
node = ExampleCodeExecutionNode()
|
860
|
+
outputs = node.run()
|
861
|
+
|
862
|
+
# THEN the node should successfully access the string value through the .value property
|
863
|
+
assert outputs == {"result": "hello", "log": ""}
|
864
|
+
|
865
|
+
|
866
|
+
def test_run_node__string_value_wrapper__list_of_dicts():
|
867
|
+
# GIVEN a node that accesses the 'value' property of a string input
|
868
|
+
class ExampleCodeExecutionNode(CodeExecutionNode[BaseState, Any]):
|
869
|
+
code = """\
|
870
|
+
def main(output: list[str]) -> list[str]:
|
871
|
+
results = []
|
872
|
+
for item in output:
|
873
|
+
results.append(item['value'])
|
874
|
+
|
875
|
+
return results
|
876
|
+
"""
|
877
|
+
code_inputs = {"output": ['{"foo": "bar"}', '{"foo2": "bar2"}']}
|
878
|
+
runtime = "PYTHON_3_11_6"
|
879
|
+
|
880
|
+
# WHEN we run the node
|
881
|
+
node = ExampleCodeExecutionNode()
|
882
|
+
outputs = node.run()
|
883
|
+
|
884
|
+
# THEN the node should successfully access the string value
|
885
|
+
assert outputs == {"result": ['{"foo": "bar"}', '{"foo2": "bar2"}'], "log": ""}
|
@@ -8,6 +8,7 @@ from vellum.workflows.errors.types import WorkflowErrorCode
|
|
8
8
|
from vellum.workflows.exceptions import NodeException
|
9
9
|
from vellum.workflows.nodes.utils import cast_to_output_type
|
10
10
|
from vellum.workflows.state.context import WorkflowContext
|
11
|
+
from vellum.workflows.types.code_execution_node_wrappers import ListWrapper, clean_for_dict_wrapper
|
11
12
|
from vellum.workflows.types.core import EntityInputsInterface
|
12
13
|
|
13
14
|
|
@@ -35,58 +36,6 @@ def read_file_from_path(
|
|
35
36
|
return None
|
36
37
|
|
37
38
|
|
38
|
-
class ListWrapper(list):
|
39
|
-
def __getitem__(self, key):
|
40
|
-
item = super().__getitem__(key)
|
41
|
-
if not isinstance(item, DictWrapper) and not isinstance(item, ListWrapper):
|
42
|
-
self.__setitem__(key, _clean_for_dict_wrapper(item))
|
43
|
-
|
44
|
-
return super().__getitem__(key)
|
45
|
-
|
46
|
-
|
47
|
-
class DictWrapper(dict):
|
48
|
-
"""
|
49
|
-
This wraps a dict object to make it behave basically the same as a standard javascript object
|
50
|
-
and enables us to use vellum types here without a shared library since we don't actually
|
51
|
-
typecheck things here.
|
52
|
-
"""
|
53
|
-
|
54
|
-
def __getitem__(self, key):
|
55
|
-
return self.__getattr__(key)
|
56
|
-
|
57
|
-
def __getattr__(self, attr):
|
58
|
-
if attr not in self:
|
59
|
-
if attr == "value":
|
60
|
-
# In order to be backwards compatible with legacy Workflows, which wrapped
|
61
|
-
# several values as VellumValue objects, we use the "value" key to return itself
|
62
|
-
return self
|
63
|
-
|
64
|
-
raise AttributeError(f"dict has no key: '{attr}'")
|
65
|
-
|
66
|
-
item = super().__getitem__(attr)
|
67
|
-
if not isinstance(item, DictWrapper) and not isinstance(item, ListWrapper):
|
68
|
-
self.__setattr__(attr, _clean_for_dict_wrapper(item))
|
69
|
-
|
70
|
-
return super().__getitem__(attr)
|
71
|
-
|
72
|
-
def __setattr__(self, name, value):
|
73
|
-
self[name] = value
|
74
|
-
|
75
|
-
|
76
|
-
def _clean_for_dict_wrapper(obj):
|
77
|
-
if isinstance(obj, dict):
|
78
|
-
wrapped = DictWrapper(obj)
|
79
|
-
for key in wrapped:
|
80
|
-
wrapped[key] = _clean_for_dict_wrapper(wrapped[key])
|
81
|
-
|
82
|
-
return wrapped
|
83
|
-
|
84
|
-
elif isinstance(obj, list):
|
85
|
-
return ListWrapper(map(lambda item: _clean_for_dict_wrapper(item), obj))
|
86
|
-
|
87
|
-
return obj
|
88
|
-
|
89
|
-
|
90
39
|
def run_code_inline(
|
91
40
|
code: str,
|
92
41
|
inputs: EntityInputsInterface,
|
@@ -107,12 +56,12 @@ def run_code_inline(
|
|
107
56
|
(
|
108
57
|
item.model_dump()
|
109
58
|
if isinstance(item, BaseModel)
|
110
|
-
else
|
59
|
+
else clean_for_dict_wrapper(item) if isinstance(item, (dict, list, str)) else item
|
111
60
|
)
|
112
61
|
for item in value
|
113
62
|
]
|
114
63
|
)
|
115
|
-
return
|
64
|
+
return clean_for_dict_wrapper(value)
|
116
65
|
|
117
66
|
exec_globals = {
|
118
67
|
"__arg__inputs": {name: wrap_value(value) for name, value in inputs.items()},
|
@@ -9,7 +9,6 @@ from vellum import (
|
|
9
9
|
PromptOutput,
|
10
10
|
StringVellumValue,
|
11
11
|
)
|
12
|
-
from vellum.workflows.constants import OMIT
|
13
12
|
from vellum.workflows.inputs import BaseInputs
|
14
13
|
from vellum.workflows.nodes import PromptDeploymentNode
|
15
14
|
from vellum.workflows.state import BaseState
|
@@ -66,14 +65,14 @@ def test_text_prompt_deployment_node__basic(vellum_client):
|
|
66
65
|
|
67
66
|
# AND we should have made the expected call to stream the prompt execution
|
68
67
|
vellum_client.execute_prompt_stream.assert_called_once_with(
|
69
|
-
expand_meta=
|
70
|
-
expand_raw=
|
71
|
-
external_id=
|
68
|
+
expand_meta=None,
|
69
|
+
expand_raw=None,
|
70
|
+
external_id=None,
|
72
71
|
inputs=[],
|
73
|
-
metadata=
|
72
|
+
metadata=None,
|
74
73
|
prompt_deployment_id=None,
|
75
74
|
prompt_deployment_name="my-deployment",
|
76
|
-
raw_overrides=
|
75
|
+
raw_overrides=None,
|
77
76
|
release_tag="LATEST",
|
78
77
|
request_options={
|
79
78
|
"additional_body_parameters": {"execution_context": {"parent_context": None, "trace_id": mock.ANY}}
|
vellum/workflows/nodes/utils.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
from functools import cache
|
2
|
+
import inspect
|
2
3
|
import json
|
3
4
|
import sys
|
4
5
|
from types import ModuleType
|
@@ -14,6 +15,7 @@ from vellum.workflows.nodes import BaseNode
|
|
14
15
|
from vellum.workflows.nodes.bases.base_adornment_node import BaseAdornmentNode
|
15
16
|
from vellum.workflows.ports.port import Port
|
16
17
|
from vellum.workflows.state.base import BaseState
|
18
|
+
from vellum.workflows.types.code_execution_node_wrappers import StringValueWrapper
|
17
19
|
from vellum.workflows.types.core import Json
|
18
20
|
from vellum.workflows.types.generics import NodeType
|
19
21
|
|
@@ -176,6 +178,8 @@ def parse_type_from_str(result_as_str: str, output_type: Any) -> Any:
|
|
176
178
|
|
177
179
|
|
178
180
|
def _get_type_name(obj: Any) -> str:
|
181
|
+
if inspect.isclass(obj) and issubclass(obj, StringValueWrapper):
|
182
|
+
return "str"
|
179
183
|
if isinstance(obj, type):
|
180
184
|
return obj.__name__
|
181
185
|
|
@@ -0,0 +1,64 @@
|
|
1
|
+
class StringValueWrapper(str):
|
2
|
+
def __getitem__(self, key):
|
3
|
+
if key == "value":
|
4
|
+
return self
|
5
|
+
raise KeyError(key)
|
6
|
+
|
7
|
+
def __getattr__(self, attr):
|
8
|
+
if attr == "value":
|
9
|
+
return self
|
10
|
+
raise AttributeError(f"'str' object has no attribute '{attr}'")
|
11
|
+
|
12
|
+
|
13
|
+
class ListWrapper(list):
|
14
|
+
def __getitem__(self, key):
|
15
|
+
item = super().__getitem__(key)
|
16
|
+
if not isinstance(item, DictWrapper) and not isinstance(item, ListWrapper):
|
17
|
+
self.__setitem__(key, clean_for_dict_wrapper(item))
|
18
|
+
|
19
|
+
return super().__getitem__(key)
|
20
|
+
|
21
|
+
|
22
|
+
class DictWrapper(dict):
|
23
|
+
"""
|
24
|
+
This wraps a dict object to make it behave basically the same as a standard javascript object
|
25
|
+
and enables us to use vellum types here without a shared library since we don't actually
|
26
|
+
typecheck things here.
|
27
|
+
"""
|
28
|
+
|
29
|
+
def __getitem__(self, key):
|
30
|
+
return self.__getattr__(key)
|
31
|
+
|
32
|
+
def __getattr__(self, attr):
|
33
|
+
if attr not in self:
|
34
|
+
if attr == "value":
|
35
|
+
# In order to be backwards compatible with legacy Workflows, which wrapped
|
36
|
+
# several values as VellumValue objects, we use the "value" key to return itself
|
37
|
+
return self
|
38
|
+
|
39
|
+
raise AttributeError(f"dict has no key: '{attr}'")
|
40
|
+
|
41
|
+
item = super().__getitem__(attr)
|
42
|
+
if not isinstance(item, DictWrapper) and not isinstance(item, ListWrapper):
|
43
|
+
self.__setattr__(attr, clean_for_dict_wrapper(item))
|
44
|
+
|
45
|
+
return super().__getitem__(attr)
|
46
|
+
|
47
|
+
def __setattr__(self, name, value):
|
48
|
+
self[name] = value
|
49
|
+
|
50
|
+
|
51
|
+
def clean_for_dict_wrapper(obj):
|
52
|
+
if isinstance(obj, dict):
|
53
|
+
wrapped = DictWrapper(obj)
|
54
|
+
for key in wrapped:
|
55
|
+
wrapped[key] = clean_for_dict_wrapper(wrapped[key])
|
56
|
+
|
57
|
+
return wrapped
|
58
|
+
|
59
|
+
elif isinstance(obj, list):
|
60
|
+
return ListWrapper(map(lambda item: clean_for_dict_wrapper(item), obj))
|
61
|
+
elif isinstance(obj, str):
|
62
|
+
return StringValueWrapper(obj)
|
63
|
+
|
64
|
+
return obj
|
@@ -1,22 +1,34 @@
|
|
1
1
|
import os
|
2
|
-
from typing import Optional
|
2
|
+
from typing import List, Optional
|
3
3
|
|
4
4
|
from vellum import Vellum, VellumEnvironment
|
5
5
|
|
6
6
|
|
7
|
-
def create_vellum_client(api_key: Optional[str] = None) -> Vellum:
|
7
|
+
def create_vellum_client(api_key: Optional[str] = None, api_url: Optional[str] = None) -> Vellum:
|
8
8
|
if api_key is None:
|
9
9
|
api_key = os.getenv("VELLUM_API_KEY", default="")
|
10
10
|
|
11
11
|
return Vellum(
|
12
12
|
api_key=api_key,
|
13
|
-
environment=create_vellum_environment(),
|
13
|
+
environment=create_vellum_environment(api_url),
|
14
14
|
)
|
15
15
|
|
16
16
|
|
17
|
-
def create_vellum_environment() -> VellumEnvironment:
|
17
|
+
def create_vellum_environment(api_url: Optional[str] = None) -> VellumEnvironment:
|
18
18
|
return VellumEnvironment(
|
19
|
-
default=
|
20
|
-
documents=
|
21
|
-
predict=
|
19
|
+
default=_resolve_env([api_url, "VELLUM_DEFAULT_API_URL", "VELLUM_API_URL"], "https://api.vellum.ai"),
|
20
|
+
documents=_resolve_env([api_url, "VELLUM_DOCUMENTS_API_URL", "VELLUM_API_URL"], "https://documents.vellum.ai"),
|
21
|
+
predict=_resolve_env([api_url, "VELLUM_PREDICT_API_URL", "VELLUM_API_URL"], "https://predict.vellum.ai"),
|
22
22
|
)
|
23
|
+
|
24
|
+
|
25
|
+
def _resolve_env(names: List[Optional[str]], default: str = "") -> str:
|
26
|
+
for name in names:
|
27
|
+
if not name:
|
28
|
+
continue
|
29
|
+
|
30
|
+
value = os.getenv(name)
|
31
|
+
if value:
|
32
|
+
return value
|
33
|
+
|
34
|
+
return default
|
@@ -2,13 +2,13 @@ vellum_cli/CONTRIBUTING.md,sha256=FtDC7BGxSeMnwCXAUssFsAIElXtmJE-O5Z7BpolcgvI,29
|
|
2
2
|
vellum_cli/README.md,sha256=2NudRoLzWxNKqnuVy1JuQ7DerIaxWGYkrH8kMd-asIE,90
|
3
3
|
vellum_cli/__init__.py,sha256=7aO9XFnaEVRiVshn86cFudebFUccT-gV8xIARJWqKYo,12257
|
4
4
|
vellum_cli/aliased_group.py,sha256=ugW498j0yv4ALJ8vS9MsO7ctDW7Jlir9j6nE_uHAP8c,3363
|
5
|
-
vellum_cli/config.py,sha256=
|
5
|
+
vellum_cli/config.py,sha256=v5BmZ-t_v4Jmqd7KVuQMZF2pRI-rbMspSkVYXIRoTmI,9448
|
6
6
|
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
10
|
vellum_cli/pull.py,sha256=2hSJGeqooevMb--mcvRLQ1GYT-9290cI7VdSRifzmTg,12561
|
11
|
-
vellum_cli/push.py,sha256=
|
11
|
+
vellum_cli/push.py,sha256=nWHLDi_w0LXycNkVv00CiNwY469BcTNBn7NphWpCA7E,9711
|
12
12
|
vellum_cli/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
13
|
vellum_cli/tests/conftest.py,sha256=AFYZryKA2qnUuCPBxBKmHLFoPiE0WhBFFej9tNwSHdc,1526
|
14
14
|
vellum_cli/tests/test_config.py,sha256=uvKGDc8BoVyT9_H0Z-g8469zVxomn6Oi3Zj-vK7O_wU,2631
|
@@ -17,7 +17,7 @@ vellum_cli/tests/test_init.py,sha256=8UOc_ThfouR4ja5cCl_URuLk7ohr9JXfCnG4yka1OUQ
|
|
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
19
|
vellum_cli/tests/test_pull.py,sha256=iTxVbJGuehvgNt8Vp9W3Y5Bvaocfws8bl8LMGEbc_qQ,47508
|
20
|
-
vellum_cli/tests/test_push.py,sha256=
|
20
|
+
vellum_cli/tests/test_push.py,sha256=uNMmPG9Z0uRN6xYYMzBGZaCXJZkAHWcbcSJRJ4eQk70,31182
|
21
21
|
vellum_ee/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
22
|
vellum_ee/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
23
23
|
vellum_ee/workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -45,10 +45,10 @@ vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py,sha256=yZO9U
|
|
45
45
|
vellum_ee/workflows/display/nodes/vellum/map_node.py,sha256=T3a6Lv51SC1506bTVd8T9y_KVmP2VP4IQarAO87xdmM,3755
|
46
46
|
vellum_ee/workflows/display/nodes/vellum/merge_node.py,sha256=yBWeN4T_lOsDVnNOKWRiT7JYKu0IR5Fx2z99iq6QKSA,3273
|
47
47
|
vellum_ee/workflows/display/nodes/vellum/note_node.py,sha256=3E0UqmgVYdtbj4nyq8gKju8EpMsRHMCQ0KLrJhug3XU,1084
|
48
|
-
vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py,sha256=
|
48
|
+
vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py,sha256=NCh9T7M4V1w-5i_bfYdI6L4jj1C_JGBuVBb0nXXsN38,3239
|
49
49
|
vellum_ee/workflows/display/nodes/vellum/retry_node.py,sha256=X3xnlAU5JisL0jRvaG_V9RvTF7ZlGufTO8tXLLVhGIg,3280
|
50
50
|
vellum_ee/workflows/display/nodes/vellum/search_node.py,sha256=7vU_4IxYe7iwn4p7J909cxF1TOR-tUlFXA7k3ySQPwM,9320
|
51
|
-
vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py,sha256=
|
51
|
+
vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py,sha256=TIMpOL0dm__xvnDHotCEjBQWCp2hgRDJUnRuPMBrZcE,2592
|
52
52
|
vellum_ee/workflows/display/nodes/vellum/templating_node.py,sha256=Nk5pxly4d-kactJ3Z4SLErZCm8hicyj2rCArZw8pW9k,3283
|
53
53
|
vellum_ee/workflows/display/nodes/vellum/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
54
54
|
vellum_ee/workflows/display/nodes/vellum/tests/test_code_execution_node.py,sha256=OoNO-BstB96F-VMK6FZ9aXyi-0wyNePo6HiaJC6SYRw,3880
|
@@ -91,17 +91,17 @@ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_n
|
|
91
91
|
vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py,sha256=r748dpS13HtwY7t_KQFExFssxRy0xI2d-wxmhiUHRe0,3850
|
92
92
|
vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py,sha256=EL5kfakuoEcwD85dGjhMta-J-PpCHRSDoc80SdbBrQk,2769
|
93
93
|
vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py,sha256=RmFUDx8dYdfsOE2CGLvdXqNNRtLLpVzXDN8dqZyMcZ8,5822
|
94
|
-
vellum_ee/workflows/display/types.py,sha256=
|
94
|
+
vellum_ee/workflows/display/types.py,sha256=i4T7ElU5b5h-nA1i3scmEhO1BqmNDc4eJDHavATD88w,2821
|
95
95
|
vellum_ee/workflows/display/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
96
96
|
vellum_ee/workflows/display/utils/exceptions.py,sha256=LSwwxCYNxFkf5XMUcFkaZKpQ13OSrI7y_bpEUwbKVk0,169
|
97
|
-
vellum_ee/workflows/display/utils/expressions.py,sha256=
|
97
|
+
vellum_ee/workflows/display/utils/expressions.py,sha256=Q0Vf-88wtbOIM1ZRkAaF5tMZc2V-i8LeZ32wFmHFmZg,10642
|
98
98
|
vellum_ee/workflows/display/utils/registry.py,sha256=fWIm5Jj-10gNFjgn34iBu4RWv3Vd15ijtSN0V97bpW8,1513
|
99
|
-
vellum_ee/workflows/display/utils/vellum.py,sha256=
|
99
|
+
vellum_ee/workflows/display/utils/vellum.py,sha256=HDe1vtIaU35OEg4oC1KC6WNwhw5Laf_mNURorzbeutQ,5418
|
100
100
|
vellum_ee/workflows/display/vellum.py,sha256=o7mq_vk2Yapu9DDKRz5l76h8EmCAypWGQYe6pryrbB8,3576
|
101
101
|
vellum_ee/workflows/display/workflows/__init__.py,sha256=kapXsC67VJcgSuiBMa86FdePG5A9kMB5Pi4Uy1O2ob4,207
|
102
|
-
vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256=
|
103
|
-
vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py,sha256=
|
104
|
-
vellum_ee/workflows/display/workflows/tests/test_workflow_display.py,sha256=
|
102
|
+
vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256=NuWlnGNe3Htcfh-l_8e37uitdUsy6WZNB7W7dYcCoUg,33355
|
103
|
+
vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py,sha256=gxz76AeCqgAZ9D2lZeTiZzxY9eMgn3qOSfVgiqYcOh8,2028
|
104
|
+
vellum_ee/workflows/display/workflows/tests/test_workflow_display.py,sha256=U0LsUqjJ-5qrkqgFsvdWzqWX7OHEMzsDCWrXR1xyzp0,15599
|
105
105
|
vellum_ee/workflows/display/workflows/vellum_workflow_display.py,sha256=aaKdmWrgEe5YyV4zuDY_4E3y-l59rIHQnNGiPj2OWxQ,359
|
106
106
|
vellum_ee/workflows/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
107
107
|
vellum_ee/workflows/server/virtual_file_loader.py,sha256=7JphJcSO3H85qiC2DpFfBWjC3JjrbRmoynBC6KKHVsA,2710
|
@@ -132,7 +132,7 @@ vellum/client/README.md,sha256=JkCJjmMZl4jrPj46pkmL9dpK4gSzQQmP5I7z4aME4LY,4749
|
|
132
132
|
vellum/client/__init__.py,sha256=Z-JHK2jGxhtTtmkLeOaUGGJWIUNYGNVBLvUewC6lp6w,118148
|
133
133
|
vellum/client/core/__init__.py,sha256=SQ85PF84B9MuKnBwHNHWemSGuy-g_515gFYNFhvEE0I,1438
|
134
134
|
vellum/client/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
|
135
|
-
vellum/client/core/client_wrapper.py,sha256=
|
135
|
+
vellum/client/core/client_wrapper.py,sha256=Bo-z8mq3B7ugaNmdHcHDd0_iCRPsJMoD6YQfXPjlnC8,1869
|
136
136
|
vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
|
137
137
|
vellum/client/core/file.py,sha256=X9IbmkZmB2bB_DpmZAO3crWdXagOakAyn6UCOCImCPg,2322
|
138
138
|
vellum/client/core/http_client.py,sha256=R0pQpCppnEtxccGvXl4uJ76s7ro_65Fo_erlNNLp_AI,19228
|
@@ -1562,9 +1562,9 @@ vellum/workflows/nodes/core/templating_node/__init__.py,sha256=GmyuYo81_A1_Bz6id
|
|
1562
1562
|
vellum/workflows/nodes/core/templating_node/node.py,sha256=iqBmr2i-f-BqhisNQJiDfewjol0ur7-XpupLStyMJsg,3731
|
1563
1563
|
vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py,sha256=nXkgGDBg4wP36NwykdMEVWwx_xjv8oGT2rYkwuCB_VU,10075
|
1564
1564
|
vellum/workflows/nodes/core/try_node/__init__.py,sha256=JVD4DrldTIqFQQFrubs9KtWCCc0YCAc7Fzol5ZWIWeM,56
|
1565
|
-
vellum/workflows/nodes/core/try_node/node.py,sha256=
|
1565
|
+
vellum/workflows/nodes/core/try_node/node.py,sha256=XdyOvlwQ3m4h0-_WNtaBl2t_CdlzPXclulkLOtUcX3E,4388
|
1566
1566
|
vellum/workflows/nodes/core/try_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1567
|
-
vellum/workflows/nodes/core/try_node/tests/test_node.py,sha256=
|
1567
|
+
vellum/workflows/nodes/core/try_node/tests/test_node.py,sha256=h6eUc3SggvhzBWlOD0PrPUlkoCSQHwjqYn81VkxSIxU,4948
|
1568
1568
|
vellum/workflows/nodes/displayable/__init__.py,sha256=6F_4DlSwvHuilWnIalp8iDjjDXl0Nmz4QzJV2PYe5RI,1023
|
1569
1569
|
vellum/workflows/nodes/displayable/api_node/__init__.py,sha256=MoxdQSnidIj1Nf_d-hTxlOxcZXaZnsWFDbE-PkTK24o,56
|
1570
1570
|
vellum/workflows/nodes/displayable/api_node/node.py,sha256=cp0nAukcOpM6TcNhbz12h08TMJxp_LM-MLDl1dAzYsk,2534
|
@@ -1580,7 +1580,7 @@ vellum/workflows/nodes/displayable/bases/inline_prompt_node/constants.py,sha256=
|
|
1580
1580
|
vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py,sha256=wqN1EjyjTL6McUmlkHWu3GXVzcNaqDjavvmKUHDaVqg,10623
|
1581
1581
|
vellum/workflows/nodes/displayable/bases/inline_prompt_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1582
1582
|
vellum/workflows/nodes/displayable/bases/inline_prompt_node/tests/test_inline_prompt_node.py,sha256=YPOFoaEBENfOzE_qWo3WdQ_E1dQk78aLCWk8gOMvTjg,16042
|
1583
|
-
vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py,sha256=
|
1583
|
+
vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py,sha256=T99UWACTD9ytVDVHa6W2go00V7HNwDxOyBFyMM2GnhQ,9567
|
1584
1584
|
vellum/workflows/nodes/displayable/bases/search_node.py,sha256=3UtbqY3QO4kzfJHbmUNZGnEEfJmaoiF892u8H6TGjp8,5381
|
1585
1585
|
vellum/workflows/nodes/displayable/bases/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1586
1586
|
vellum/workflows/nodes/displayable/bases/tests/test_utils.py,sha256=eqdqbKNRWVMDPevgwLg1i6YK0g4L4bCy-7xCBN5yYZI,3156
|
@@ -1591,8 +1591,8 @@ vellum/workflows/nodes/displayable/code_execution_node/node.py,sha256=Ko_Dy17Ajf
|
|
1591
1591
|
vellum/workflows/nodes/displayable/code_execution_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1592
1592
|
vellum/workflows/nodes/displayable/code_execution_node/tests/fixtures/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1593
1593
|
vellum/workflows/nodes/displayable/code_execution_node/tests/fixtures/main.py,sha256=5QsbmkzSlSbcbWTG_JmIqcP-JNJzOPTKxGzdHos19W4,79
|
1594
|
-
vellum/workflows/nodes/displayable/code_execution_node/tests/test_code_execution_node.py,sha256=
|
1595
|
-
vellum/workflows/nodes/displayable/code_execution_node/utils.py,sha256=
|
1594
|
+
vellum/workflows/nodes/displayable/code_execution_node/tests/test_code_execution_node.py,sha256=Km_BH9W61IJSRj5CdiSmEOINOIouG_a5Gey0fCDmShQ,26620
|
1595
|
+
vellum/workflows/nodes/displayable/code_execution_node/utils.py,sha256=oCI8HS_Y-hsNhvGIC8HgbIzKIZeWOkXMLaknDRf-qus,2928
|
1596
1596
|
vellum/workflows/nodes/displayable/conditional_node/__init__.py,sha256=AS_EIqFdU1F9t8aLmbZU-rLh9ry6LCJ0uj0D8F0L5Uw,72
|
1597
1597
|
vellum/workflows/nodes/displayable/conditional_node/node.py,sha256=Qjfl33gZ3JEgxBA1EgzSUebboGvsARthIxxcQyvx5Gg,1152
|
1598
1598
|
vellum/workflows/nodes/displayable/conftest.py,sha256=K2kLM2JGAfcrmmd92u8DXInUO5klFdggPWblg5RVcx4,5729
|
@@ -1628,7 +1628,7 @@ vellum/workflows/nodes/displayable/subworkflow_deployment_node/tests/test_node.p
|
|
1628
1628
|
vellum/workflows/nodes/displayable/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1629
1629
|
vellum/workflows/nodes/displayable/tests/test_inline_text_prompt_node.py,sha256=LaxohBcKfSW2PSiBBlx67FdW_q4YC2BM2ouH-vuGPAA,4700
|
1630
1630
|
vellum/workflows/nodes/displayable/tests/test_search_node_wth_text_output.py,sha256=VepO5z1277c1y5N6LLIC31nnWD1aak2m5oPFplfJHHs,6935
|
1631
|
-
vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py,sha256=
|
1631
|
+
vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py,sha256=dc3EEn1sOICpr3GdS8eyeFtExaGwWWcw9eHSdkRhQJU,2584
|
1632
1632
|
vellum/workflows/nodes/experimental/README.md,sha256=eF6DfIL8t-HbF9-mcofOMymKrraiBHDLKTlnBa51ZiE,284
|
1633
1633
|
vellum/workflows/nodes/experimental/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1634
1634
|
vellum/workflows/nodes/experimental/openai_chat_completion_node/__init__.py,sha256=lsyD9laR9p7kx5-BXGH2gUTM242UhKy8SMV0SR6S2iE,90
|
@@ -1640,7 +1640,7 @@ vellum/workflows/nodes/mocks.py,sha256=a1FjWEIocseMfjzM-i8DNozpUsaW0IONRpZmXBoWl
|
|
1640
1640
|
vellum/workflows/nodes/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1641
1641
|
vellum/workflows/nodes/tests/test_mocks.py,sha256=mfPvrs75PKcsNsbJLQAN6PDFoVqs9TmQxpdyFKDdO60,7837
|
1642
1642
|
vellum/workflows/nodes/tests/test_utils.py,sha256=qNB6ApIsnFtE_9HDaEah9KD-zX8e10FhDixewS1uRcc,5199
|
1643
|
-
vellum/workflows/nodes/utils.py,sha256=
|
1643
|
+
vellum/workflows/nodes/utils.py,sha256=j3I_qKlkU9WDplYbeija3-rC_KAKD4dyums1xROWFKQ,9193
|
1644
1644
|
vellum/workflows/outputs/__init__.py,sha256=AyZ4pRh_ACQIGvkf0byJO46EDnSix1ZCAXfvh-ms1QE,94
|
1645
1645
|
vellum/workflows/outputs/base.py,sha256=1OGHqBJVk7i8cW8uewFWOhIjuMlRRpzCDrGE30ZwDjw,8763
|
1646
1646
|
vellum/workflows/ports/__init__.py,sha256=bZuMt-R7z5bKwpu4uPW7LlJeePOQWmCcDSXe5frUY5g,101
|
@@ -1676,6 +1676,7 @@ vellum/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
|
|
1676
1676
|
vellum/workflows/tests/test_sandbox.py,sha256=JKwaluI-lODQo7Ek9sjDstjL_WTdSqUlVik6ZVTfVOA,1826
|
1677
1677
|
vellum/workflows/tests/test_undefined.py,sha256=zMCVliCXVNLrlC6hEGyOWDnQADJ2g83yc5FIM33zuo8,353
|
1678
1678
|
vellum/workflows/types/__init__.py,sha256=KxUTMBGzuRCfiMqzzsykOeVvrrkaZmTTo1a7SLu8gRM,68
|
1679
|
+
vellum/workflows/types/code_execution_node_wrappers.py,sha256=cQ1Se6fe1uqGUs8uVQxkk2OEVikcHbwTM0CyU2AsgqI,2010
|
1679
1680
|
vellum/workflows/types/core.py,sha256=kMQremh_I8egXpiKmtMQbB6e3OczAWiRnnTq5V6xlD0,928
|
1680
1681
|
vellum/workflows/types/definition.py,sha256=z81CL_u0FJol-9yUIqoXNTYAARtU8x__c6s-f4rb5c8,2335
|
1681
1682
|
vellum/workflows/types/generics.py,sha256=tKXz0LwWJGKw1YGudyl9_yFDrRgU6yYV1yJV1Zv-LTw,1430
|
@@ -1693,15 +1694,15 @@ vellum/workflows/utils/tests/test_uuids.py,sha256=i77ABQ0M3S-aFLzDXHJq_yr5FPkJEW
|
|
1693
1694
|
vellum/workflows/utils/tests/test_vellum_variables.py,sha256=maI5e7Od7UlpMwlrOrcdlXqnFhonkXGnWq8G2-YQLi8,1155
|
1694
1695
|
vellum/workflows/utils/uuids.py,sha256=DFzPv9RCvsKhvdTEIQyfSek2A31D6S_QcmeLPbgrgTY,739
|
1695
1696
|
vellum/workflows/utils/vellum_variables.py,sha256=UiGlUh0a8vel2FbW3w-xbHxSv_jNutkDdqMVtP_b42A,3385
|
1696
|
-
vellum/workflows/vellum_client.py,sha256=
|
1697
|
+
vellum/workflows/vellum_client.py,sha256=xkfoucodxNK5JR2-lbRqZx3xzDgExWkP6kySrpi_Ubc,1079
|
1697
1698
|
vellum/workflows/workflows/__init__.py,sha256=KY45TqvavCCvXIkyCFMEc0dc6jTMOUci93U2DUrlZYc,66
|
1698
1699
|
vellum/workflows/workflows/base.py,sha256=9dGZzoXbVVtw19pVhmawIA1wd1iLQttAKypuVFWb0fU,23793
|
1699
1700
|
vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnadGsrSZGa7t7LpJA,2008
|
1700
1701
|
vellum/workflows/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1701
1702
|
vellum/workflows/workflows/tests/test_base_workflow.py,sha256=8P5YIsNMO78_CR1NNK6wkEdkMB4b3Q_Ni1qxh78OnHo,20481
|
1702
1703
|
vellum/workflows/workflows/tests/test_context.py,sha256=VJBUcyWVtMa_lE5KxdhgMu0WYNYnUQUDvTF7qm89hJ0,2333
|
1703
|
-
vellum_ai-0.14.
|
1704
|
-
vellum_ai-0.14.
|
1705
|
-
vellum_ai-0.14.
|
1706
|
-
vellum_ai-0.14.
|
1707
|
-
vellum_ai-0.14.
|
1704
|
+
vellum_ai-0.14.46.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
|
1705
|
+
vellum_ai-0.14.46.dist-info/METADATA,sha256=QVjFBBT5KT2PzAvAibMrRv8VD7GpQoUhjlXaR_H--Fw,5484
|
1706
|
+
vellum_ai-0.14.46.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
1707
|
+
vellum_ai-0.14.46.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
|
1708
|
+
vellum_ai-0.14.46.dist-info/RECORD,,
|
vellum_cli/config.py
CHANGED
@@ -16,10 +16,15 @@ PYPROJECT_TOML_PATH = "pyproject.toml"
|
|
16
16
|
|
17
17
|
class WorkspaceConfig(UniversalBaseModel):
|
18
18
|
name: str
|
19
|
-
api_key: str
|
19
|
+
api_key: str = "VELLUM_API_KEY"
|
20
|
+
api_url: Optional[str] = None
|
20
21
|
|
21
22
|
def merge(self, other: "WorkspaceConfig") -> "WorkspaceConfig":
|
22
|
-
return WorkspaceConfig(
|
23
|
+
return WorkspaceConfig(
|
24
|
+
name=self.name or other.name,
|
25
|
+
api_key=self.api_key or other.api_key,
|
26
|
+
api_url=self.api_url or other.api_url,
|
27
|
+
)
|
23
28
|
|
24
29
|
|
25
30
|
DEFAULT_WORKSPACE_CONFIG = WorkspaceConfig(name="default", api_key="VELLUM_API_KEY")
|
vellum_cli/push.py
CHANGED
@@ -97,6 +97,7 @@ def push_command(
|
|
97
97
|
|
98
98
|
client = create_vellum_client(
|
99
99
|
api_key=api_key,
|
100
|
+
api_url=workspace_config.api_url,
|
100
101
|
)
|
101
102
|
sys.path.insert(0, os.getcwd())
|
102
103
|
|
@@ -105,6 +106,7 @@ def push_command(
|
|
105
106
|
workflow = BaseWorkflow.load_from_module(workflow_config.module)
|
106
107
|
workflow_display = get_workflow_display(
|
107
108
|
workflow_class=workflow,
|
109
|
+
client=client,
|
108
110
|
dry_run=dry_run or False,
|
109
111
|
)
|
110
112
|
exec_config = workflow_display.serialize()
|
@@ -234,9 +236,11 @@ def push_command(
|
|
234
236
|
"""
|
235
237
|
) # type: ignore[attr-defined]
|
236
238
|
else:
|
239
|
+
default_api_url = client._client_wrapper._environment.default
|
240
|
+
base_url = default_api_url.split("/v1")[0].replace("//api.", "//app.")
|
237
241
|
logger.info(
|
238
242
|
f"""Successfully pushed {workflow_config.module} to Vellum!
|
239
|
-
Visit at:
|
243
|
+
Visit at: {base_url}/workflow-sandboxes/{response.workflow_sandbox_id}"""
|
240
244
|
)
|
241
245
|
|
242
246
|
if not workflow_config.workflow_sandbox_id:
|
vellum_cli/tests/test_push.py
CHANGED
@@ -7,6 +7,7 @@ from unittest import mock
|
|
7
7
|
from uuid import uuid4
|
8
8
|
|
9
9
|
from click.testing import CliRunner
|
10
|
+
from httpx import Response
|
10
11
|
|
11
12
|
from vellum.client.core.api_error import ApiError
|
12
13
|
from vellum.client.types.workflow_push_response import WorkflowPushResponse
|
@@ -29,19 +30,25 @@ def _extract_tar_gz(tar_gz_bytes: bytes) -> dict[str, str]:
|
|
29
30
|
return files
|
30
31
|
|
31
32
|
|
32
|
-
def
|
33
|
-
|
33
|
+
def _ensure_file(temp_dir: str, module: str, file_name: str, content: str) -> str:
|
34
|
+
file_path = os.path.join(temp_dir, *module.split("."), file_name)
|
35
|
+
base_dir = os.path.dirname(file_path)
|
34
36
|
os.makedirs(base_dir, exist_ok=True)
|
37
|
+
|
38
|
+
with open(file_path, "w") as f:
|
39
|
+
f.write(content)
|
40
|
+
|
41
|
+
return content
|
42
|
+
|
43
|
+
|
44
|
+
def _ensure_workflow_py(temp_dir: str, module: str) -> str:
|
35
45
|
workflow_py_file_content = """\
|
36
46
|
from vellum.workflows import BaseWorkflow
|
37
47
|
|
38
48
|
class ExampleWorkflow(BaseWorkflow):
|
39
49
|
pass
|
40
50
|
"""
|
41
|
-
|
42
|
-
f.write(workflow_py_file_content)
|
43
|
-
|
44
|
-
return workflow_py_file_content
|
51
|
+
return _ensure_file(temp_dir, module, "workflow.py", workflow_py_file_content)
|
45
52
|
|
46
53
|
|
47
54
|
def test_push__no_config(mock_module):
|
@@ -133,6 +140,38 @@ def test_push__happy_path(mock_module, vellum_client, base_command):
|
|
133
140
|
assert extracted_files["workflow.py"] == workflow_py_file_content
|
134
141
|
|
135
142
|
|
143
|
+
def test_push__verify_default_url_in_raw_httpx_transport(mock_module, mock_httpx_transport):
|
144
|
+
# GIVEN a single workflow configured
|
145
|
+
module = mock_module.module
|
146
|
+
temp_dir = mock_module.temp_dir
|
147
|
+
_ensure_workflow_py(temp_dir, module)
|
148
|
+
|
149
|
+
# AND the push API call returns successfully
|
150
|
+
mock_httpx_transport.handle_request.return_value = Response(
|
151
|
+
status_code=200,
|
152
|
+
text=json.dumps(
|
153
|
+
{
|
154
|
+
"workflow_sandbox_id": str(uuid4()),
|
155
|
+
}
|
156
|
+
),
|
157
|
+
)
|
158
|
+
|
159
|
+
# WHEN calling `vellum push`
|
160
|
+
runner = CliRunner()
|
161
|
+
result = runner.invoke(cli_main, ["workflows", "push", module])
|
162
|
+
|
163
|
+
# THEN it should succeed
|
164
|
+
assert result.exit_code == 0
|
165
|
+
|
166
|
+
# AND we should have called the push API with the correct args
|
167
|
+
mock_httpx_transport.handle_request.assert_called_once()
|
168
|
+
request = mock_httpx_transport.handle_request.call_args[0][0]
|
169
|
+
assert str(request.url) == "https://api.vellum.ai/v1/workflows/push"
|
170
|
+
|
171
|
+
# AND the new URL is in the message at the end
|
172
|
+
assert "Visit at: https://app.vellum.ai/workflow-sandboxes/" in result.output
|
173
|
+
|
174
|
+
|
136
175
|
def test_push__no_config__module_found(mock_module, vellum_client):
|
137
176
|
# GIVEN no config file set
|
138
177
|
temp_dir = mock_module.temp_dir
|
@@ -486,7 +525,74 @@ Files that were different between the original project and the generated artifac
|
|
486
525
|
)
|
487
526
|
|
488
527
|
|
489
|
-
|
528
|
+
@pytest.mark.parametrize(
|
529
|
+
"file_data",
|
530
|
+
[
|
531
|
+
{
|
532
|
+
"workflow.py": """\
|
533
|
+
from vellum.workflows import BaseWorkflow
|
534
|
+
|
535
|
+
class ExampleWorkflow(BaseWorkflow):
|
536
|
+
pass
|
537
|
+
"""
|
538
|
+
},
|
539
|
+
{
|
540
|
+
"nodes/start_node.py": """\
|
541
|
+
from vellum.workflows.nodes import CodeExecutionNode
|
542
|
+
from vellum.workflows.references import VellumSecretReference
|
543
|
+
|
544
|
+
class StartNode(CodeExecutionNode):
|
545
|
+
code_inputs = {
|
546
|
+
"foo": VellumSecretReference("MY_SECRET_KEY"),
|
547
|
+
}
|
548
|
+
""",
|
549
|
+
"workflow.py": """\
|
550
|
+
from vellum.workflows import BaseWorkflow
|
551
|
+
from .nodes.start_node import StartNode
|
552
|
+
|
553
|
+
class ExampleWorkflow(BaseWorkflow):
|
554
|
+
graph = StartNode
|
555
|
+
""",
|
556
|
+
},
|
557
|
+
{
|
558
|
+
"nodes/start_node.py": """\
|
559
|
+
from vellum.workflows.nodes import PromptDeploymentNode
|
560
|
+
|
561
|
+
class StartNode(PromptDeploymentNode):
|
562
|
+
deployment = "my-deployment"
|
563
|
+
""",
|
564
|
+
"workflow.py": """\
|
565
|
+
from vellum.workflows import BaseWorkflow
|
566
|
+
from .nodes.start_node import StartNode
|
567
|
+
|
568
|
+
class ExampleWorkflow(BaseWorkflow):
|
569
|
+
graph = StartNode
|
570
|
+
""",
|
571
|
+
},
|
572
|
+
{
|
573
|
+
"nodes/start_node.py": """\
|
574
|
+
from vellum.workflows.nodes import SubworkflowDeploymentNode
|
575
|
+
|
576
|
+
class StartNode(SubworkflowDeploymentNode):
|
577
|
+
deployment = "my-deployment"
|
578
|
+
""",
|
579
|
+
"workflow.py": """\
|
580
|
+
from vellum.workflows import BaseWorkflow
|
581
|
+
from .nodes.start_node import StartNode
|
582
|
+
|
583
|
+
class ExampleWorkflow(BaseWorkflow):
|
584
|
+
graph = StartNode
|
585
|
+
""",
|
586
|
+
},
|
587
|
+
],
|
588
|
+
ids=[
|
589
|
+
"base_case",
|
590
|
+
"with_secret_reference",
|
591
|
+
"with_prompt_deployment",
|
592
|
+
"with_subworkflow_deployment",
|
593
|
+
],
|
594
|
+
)
|
595
|
+
def test_push__workspace_option__uses_different_api_key(mock_module, vellum_client_class, file_data):
|
490
596
|
# GIVEN a single workflow configured
|
491
597
|
temp_dir = mock_module.temp_dir
|
492
598
|
module = mock_module.module
|
@@ -521,7 +627,8 @@ MY_OTHER_VELLUM_API_KEY=aaabbbcccddd
|
|
521
627
|
)
|
522
628
|
|
523
629
|
# AND a workflow exists in the module successfully
|
524
|
-
|
630
|
+
for file_name, content in file_data.items():
|
631
|
+
_ensure_file(temp_dir, module, file_name, content)
|
525
632
|
|
526
633
|
# AND the push API call returns a new workflow sandbox id
|
527
634
|
new_workflow_sandbox_id = str(uuid4())
|
@@ -564,6 +671,83 @@ MY_OTHER_VELLUM_API_KEY=aaabbbcccddd
|
|
564
671
|
}
|
565
672
|
|
566
673
|
|
674
|
+
def test_push__workspace_option__uses_different_api_url_env(mock_module, mock_httpx_transport):
|
675
|
+
# GIVEN a single workflow configured
|
676
|
+
temp_dir = mock_module.temp_dir
|
677
|
+
module = mock_module.module
|
678
|
+
workflow_sandbox_id = mock_module.workflow_sandbox_id
|
679
|
+
set_pyproject_toml = mock_module.set_pyproject_toml
|
680
|
+
|
681
|
+
# AND a different workspace is set in the pyproject.toml
|
682
|
+
set_pyproject_toml(
|
683
|
+
{
|
684
|
+
"workflows": [
|
685
|
+
{
|
686
|
+
"module": module,
|
687
|
+
"workflow_sandbox_id": workflow_sandbox_id,
|
688
|
+
}
|
689
|
+
],
|
690
|
+
"workspaces": [
|
691
|
+
{
|
692
|
+
"name": "my_other_workspace",
|
693
|
+
"api_url": "MY_OTHER_VELLUM_API_URL",
|
694
|
+
}
|
695
|
+
],
|
696
|
+
}
|
697
|
+
)
|
698
|
+
|
699
|
+
# AND the .env file has the other api key stored
|
700
|
+
with open(os.path.join(temp_dir, ".env"), "w") as f:
|
701
|
+
f.write(
|
702
|
+
"""\
|
703
|
+
VELLUM_API_KEY=abcdef123456
|
704
|
+
MY_OTHER_VELLUM_API_URL=https://app.aws-vpc-staging.vellum.ai
|
705
|
+
"""
|
706
|
+
)
|
707
|
+
|
708
|
+
# AND a workflow exists in the module successfully
|
709
|
+
_ensure_workflow_py(temp_dir, module)
|
710
|
+
|
711
|
+
# AND the push API call returns a new workflow sandbox id
|
712
|
+
new_workflow_sandbox_id = str(uuid4())
|
713
|
+
mock_httpx_transport.handle_request.return_value = Response(
|
714
|
+
status_code=200,
|
715
|
+
text=json.dumps(
|
716
|
+
{
|
717
|
+
"workflow_sandbox_id": new_workflow_sandbox_id,
|
718
|
+
}
|
719
|
+
),
|
720
|
+
)
|
721
|
+
|
722
|
+
# WHEN calling `vellum push` on strict mode
|
723
|
+
runner = CliRunner()
|
724
|
+
result = runner.invoke(cli_main, ["push", module, "--workspace", "my_other_workspace"])
|
725
|
+
|
726
|
+
# THEN it should succeed
|
727
|
+
assert result.exit_code == 0, result.output
|
728
|
+
|
729
|
+
# AND we should have called the push API once with the correct api url
|
730
|
+
request = mock_httpx_transport.handle_request.call_args[0][0]
|
731
|
+
assert str(request.url) == "https://app.aws-vpc-staging.vellum.ai/v1/workflows/push"
|
732
|
+
|
733
|
+
# AND the vellum lock file should have been updated with the correct workspace
|
734
|
+
with open(os.path.join(temp_dir, "vellum.lock.json")) as f:
|
735
|
+
lock_file_content = json.load(f)
|
736
|
+
assert lock_file_content["workflows"][1] == {
|
737
|
+
"module": module,
|
738
|
+
"workflow_sandbox_id": new_workflow_sandbox_id,
|
739
|
+
"workspace": "my_other_workspace",
|
740
|
+
"container_image_name": None,
|
741
|
+
"container_image_tag": None,
|
742
|
+
"deployments": [],
|
743
|
+
"ignore": None,
|
744
|
+
"target_directory": None,
|
745
|
+
}
|
746
|
+
|
747
|
+
# AND the new URL is in the message at the end
|
748
|
+
assert "Visit at: https://app.aws-vpc-staging.vellum.ai/workflow-sandboxes/" in result.output
|
749
|
+
|
750
|
+
|
567
751
|
def test_push__workspace_option__both_options_already_configured(mock_module, vellum_client_class):
|
568
752
|
# GIVEN a single workflow configured
|
569
753
|
temp_dir = mock_module.temp_dir
|
@@ -4,7 +4,6 @@ from typing import Generic, Optional, TypeVar, cast
|
|
4
4
|
from vellum.workflows.nodes.displayable.prompt_deployment_node import PromptDeploymentNode
|
5
5
|
from vellum.workflows.references import OutputReference
|
6
6
|
from vellum.workflows.types.core import JsonObject
|
7
|
-
from vellum.workflows.vellum_client import create_vellum_client
|
8
7
|
from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
|
9
8
|
from vellum_ee.workflows.display.nodes.utils import raise_if_descriptor
|
10
9
|
from vellum_ee.workflows.display.nodes.vellum.utils import create_node_input
|
@@ -42,10 +41,7 @@ class BasePromptDeploymentNodeDisplay(BaseNodeDisplay[_PromptDeploymentNodeType]
|
|
42
41
|
_, output_display = display_context.global_node_output_displays[cast(OutputReference, node.Outputs.text)]
|
43
42
|
_, array_display = display_context.global_node_output_displays[cast(OutputReference, node.Outputs.results)]
|
44
43
|
|
45
|
-
|
46
|
-
# https://app.shortcut.com/vellum/story/4702
|
47
|
-
vellum_client = create_vellum_client()
|
48
|
-
deployment = vellum_client.deployments.retrieve(
|
44
|
+
deployment = display_context.client.deployments.retrieve(
|
49
45
|
id=str(raise_if_descriptor(node.deployment)),
|
50
46
|
)
|
51
47
|
ml_model_fallbacks = raise_if_descriptor(node.ml_model_fallbacks)
|
@@ -3,7 +3,6 @@ from typing import Generic, Optional, TypeVar
|
|
3
3
|
|
4
4
|
from vellum.workflows.nodes import SubworkflowDeploymentNode
|
5
5
|
from vellum.workflows.types.core import JsonObject
|
6
|
-
from vellum.workflows.vellum_client import create_vellum_client
|
7
6
|
from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
|
8
7
|
from vellum_ee.workflows.display.nodes.utils import raise_if_descriptor
|
9
8
|
from vellum_ee.workflows.display.nodes.vellum.utils import create_node_input
|
@@ -37,10 +36,7 @@ class BaseSubworkflowDeploymentNodeDisplay(
|
|
37
36
|
for variable_name, variable_value in subworkflow_inputs.items()
|
38
37
|
]
|
39
38
|
|
40
|
-
|
41
|
-
# https://app.shortcut.com/vellum/story/4702
|
42
|
-
vellum_client = create_vellum_client()
|
43
|
-
deployment = vellum_client.workflow_deployments.retrieve(
|
39
|
+
deployment = display_context.client.workflow_deployments.retrieve(
|
44
40
|
id=str(raise_if_descriptor(node.deployment)),
|
45
41
|
)
|
46
42
|
|
@@ -1,11 +1,13 @@
|
|
1
1
|
from dataclasses import dataclass, field
|
2
2
|
from typing import TYPE_CHECKING, Dict, Tuple, Type
|
3
3
|
|
4
|
+
from vellum.client import Vellum as VellumClient
|
4
5
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
5
6
|
from vellum.workflows.events.workflow import WorkflowEventDisplayContext # noqa: F401
|
6
7
|
from vellum.workflows.nodes import BaseNode
|
7
8
|
from vellum.workflows.ports import Port
|
8
9
|
from vellum.workflows.references import OutputReference, StateValueReference, WorkflowInputReference
|
10
|
+
from vellum.workflows.vellum_client import create_vellum_client
|
9
11
|
from vellum.workflows.workflows.base import BaseWorkflow
|
10
12
|
from vellum_ee.workflows.display.base import (
|
11
13
|
EdgeDisplay,
|
@@ -35,6 +37,7 @@ PortDisplays = Dict[Port, PortDisplay]
|
|
35
37
|
|
36
38
|
@dataclass
|
37
39
|
class WorkflowDisplayContext:
|
40
|
+
client: VellumClient = field(default_factory=create_vellum_client)
|
38
41
|
workflow_display_class: Type["BaseWorkflowDisplay"] = field(default_factory=get_default_workflow_display_class)
|
39
42
|
workflow_display: WorkflowMetaDisplay = field(default_factory=lambda: WorkflowMetaDisplay.get_default(BaseWorkflow))
|
40
43
|
workflow_input_displays: WorkflowInputsDisplays = field(default_factory=dict)
|
@@ -107,7 +107,7 @@ def get_child_descriptor(value: LazyReference, display_context: "WorkflowDisplay
|
|
107
107
|
)
|
108
108
|
|
109
109
|
node_class_name = ".".join(reference_parts[:-2])
|
110
|
-
for node in display_context.
|
110
|
+
for node in display_context.global_node_displays.keys():
|
111
111
|
if node.__name__ == node_class_name:
|
112
112
|
return getattr(node.Outputs, output_name)
|
113
113
|
|
@@ -13,7 +13,6 @@ from vellum.workflows.references.lazy import LazyReference
|
|
13
13
|
from vellum.workflows.references.node import NodeReference
|
14
14
|
from vellum.workflows.references.vellum_secret import VellumSecretReference
|
15
15
|
from vellum.workflows.utils.vellum_variables import primitive_type_to_vellum_variable_type
|
16
|
-
from vellum.workflows.vellum_client import create_vellum_client
|
17
16
|
from vellum_ee.workflows.display.utils.exceptions import UnsupportedSerializationException
|
18
17
|
from vellum_ee.workflows.display.utils.expressions import get_child_descriptor
|
19
18
|
|
@@ -118,8 +117,7 @@ def create_node_input_value_pointer_rule(
|
|
118
117
|
workflow_input_display = display_context.global_workflow_input_displays[value]
|
119
118
|
return InputVariablePointer(data=InputVariableData(input_variable_id=str(workflow_input_display.id)))
|
120
119
|
if isinstance(value, VellumSecretReference):
|
121
|
-
|
122
|
-
workspace_secret = vellum_client.workspace_secrets.retrieve(
|
120
|
+
workspace_secret = display_context.client.workspace_secrets.retrieve(
|
123
121
|
id=value.name,
|
124
122
|
)
|
125
123
|
return WorkspaceSecretPointer(
|
@@ -6,6 +6,7 @@ import logging
|
|
6
6
|
from uuid import UUID
|
7
7
|
from typing import Any, Dict, ForwardRef, Generic, Iterator, List, Optional, Tuple, Type, TypeVar, Union, cast, get_args
|
8
8
|
|
9
|
+
from vellum.client import Vellum as VellumClient
|
9
10
|
from vellum.workflows import BaseWorkflow
|
10
11
|
from vellum.workflows.constants import undefined
|
11
12
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
@@ -21,6 +22,7 @@ from vellum.workflows.types.core import JsonArray, JsonObject
|
|
21
22
|
from vellum.workflows.types.generics import WorkflowType
|
22
23
|
from vellum.workflows.types.utils import get_original_base
|
23
24
|
from vellum.workflows.utils.uuids import uuid4_from_hash
|
25
|
+
from vellum.workflows.vellum_client import create_vellum_client
|
24
26
|
from vellum_ee.workflows.display.base import (
|
25
27
|
EdgeDisplay,
|
26
28
|
EntrypointDisplay,
|
@@ -84,9 +86,16 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
|
|
84
86
|
self,
|
85
87
|
*,
|
86
88
|
parent_display_context: Optional[WorkflowDisplayContext] = None,
|
89
|
+
client: Optional[VellumClient] = None,
|
87
90
|
dry_run: bool = False,
|
88
91
|
):
|
89
92
|
self._parent_display_context = parent_display_context
|
93
|
+
self._client = client or (
|
94
|
+
# propagate the client from the parent display context if it is not provided
|
95
|
+
self._parent_display_context.client
|
96
|
+
if self._parent_display_context
|
97
|
+
else create_vellum_client()
|
98
|
+
)
|
90
99
|
self._errors: List[Exception] = []
|
91
100
|
self._dry_run = dry_run
|
92
101
|
|
@@ -494,6 +503,7 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
|
|
494
503
|
)
|
495
504
|
|
496
505
|
return WorkflowDisplayContext(
|
506
|
+
client=self._client,
|
497
507
|
workflow_display=workflow_meta_display,
|
498
508
|
workflow_input_displays=workflow_input_displays,
|
499
509
|
global_workflow_input_displays=global_workflow_input_displays,
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import types
|
2
2
|
from typing import TYPE_CHECKING, Generic, Optional, Type, TypeVar
|
3
3
|
|
4
|
+
from vellum.client import Vellum as VellumClient
|
4
5
|
from vellum.workflows.types.generics import WorkflowType
|
5
6
|
from vellum_ee.workflows.display.types import WorkflowDisplayContext
|
6
7
|
from vellum_ee.workflows.display.utils.registry import get_from_workflow_display_registry
|
@@ -35,6 +36,7 @@ def get_workflow_display(
|
|
35
36
|
*,
|
36
37
|
workflow_class: Type[WorkflowType],
|
37
38
|
parent_display_context: Optional[WorkflowDisplayContext] = None,
|
39
|
+
client: Optional[VellumClient] = None,
|
38
40
|
dry_run: bool = False,
|
39
41
|
# DEPRECATED: The following arguments will be removed in 0.15.0
|
40
42
|
root_workflow_class: Optional[Type[WorkflowType]] = None,
|
@@ -42,5 +44,6 @@ def get_workflow_display(
|
|
42
44
|
) -> "BaseWorkflowDisplay":
|
43
45
|
return _get_workflow_display_class(workflow_class=workflow_class)(
|
44
46
|
parent_display_context=parent_display_context,
|
47
|
+
client=client,
|
45
48
|
dry_run=dry_run,
|
46
49
|
)
|
@@ -7,6 +7,7 @@ from vellum.workflows.nodes.core.retry_node.node import RetryNode
|
|
7
7
|
from vellum.workflows.nodes.core.templating_node.node import TemplatingNode
|
8
8
|
from vellum.workflows.nodes.core.try_node.node import TryNode
|
9
9
|
from vellum.workflows.nodes.displayable.final_output_node.node import FinalOutputNode
|
10
|
+
from vellum.workflows.references.lazy import LazyReference
|
10
11
|
from vellum.workflows.workflows.base import BaseWorkflow
|
11
12
|
from vellum_ee.workflows.display.editor.types import NodeDisplayData, NodeDisplayPosition
|
12
13
|
from vellum_ee.workflows.display.nodes import BaseNodeDisplay
|
@@ -372,3 +373,55 @@ def test_serialize_workflow__terminal_node_mismatches_workflow_output_name():
|
|
372
373
|
"node_id": str(ExitNode.__id__),
|
373
374
|
"node_output_id": str(ExitNode.__output_ids__["value"]),
|
374
375
|
}
|
376
|
+
|
377
|
+
|
378
|
+
def test_serialize_workflow__nested_lazy_reference():
|
379
|
+
# GIVEN an inner node that references the output of an outer node
|
380
|
+
class InnerNode(BaseNode):
|
381
|
+
foo = LazyReference[str]("OuterNode.Outputs.bar")
|
382
|
+
|
383
|
+
class Outputs(BaseNode.Outputs):
|
384
|
+
foo = "foo"
|
385
|
+
|
386
|
+
# AND a workflow that uses the inner node
|
387
|
+
class InnerWorkflow(BaseWorkflow):
|
388
|
+
graph = InnerNode
|
389
|
+
|
390
|
+
class Outputs(BaseWorkflow.Outputs):
|
391
|
+
foo = InnerNode.Outputs.foo
|
392
|
+
|
393
|
+
# AND a subworkflow that uses the inner workflow
|
394
|
+
class SubworkflowNode(InlineSubworkflowNode):
|
395
|
+
subworkflow = InnerWorkflow
|
396
|
+
|
397
|
+
# AND the outer node
|
398
|
+
class OuterNode(BaseNode):
|
399
|
+
class Outputs(BaseNode.Outputs):
|
400
|
+
bar: str
|
401
|
+
|
402
|
+
# AND a workflow that uses the subworkflow node and the outer node
|
403
|
+
class MyWorkflow(BaseWorkflow):
|
404
|
+
graph = SubworkflowNode >> OuterNode
|
405
|
+
|
406
|
+
class Outputs(BaseWorkflow.Outputs):
|
407
|
+
answer = SubworkflowNode.Outputs.foo
|
408
|
+
|
409
|
+
# WHEN we serialize it
|
410
|
+
workflow_display = get_workflow_display(workflow_class=MyWorkflow)
|
411
|
+
data: dict = workflow_display.serialize()
|
412
|
+
|
413
|
+
# THEN it should have properly serialized the lazy reference
|
414
|
+
subworkflow_node = next(
|
415
|
+
node for node in data["workflow_raw_data"]["nodes"] if isinstance(node, dict) and node["type"] == "SUBWORKFLOW"
|
416
|
+
)
|
417
|
+
inner_node = next(
|
418
|
+
node
|
419
|
+
for node in subworkflow_node["data"]["workflow_raw_data"]["nodes"]
|
420
|
+
if isinstance(node, dict) and node["type"] == "GENERIC"
|
421
|
+
)
|
422
|
+
|
423
|
+
assert inner_node["attributes"][0]["value"] == {
|
424
|
+
"type": "NODE_OUTPUT",
|
425
|
+
"node_id": str(OuterNode.__id__),
|
426
|
+
"node_output_id": str(OuterNode.__output_ids__["bar"]),
|
427
|
+
}
|
File without changes
|
File without changes
|
File without changes
|