vellum-ai 0.10.6__py3-none-any.whl → 0.10.8__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- vellum/__init__.py +2 -0
- vellum/client/README.md +7 -52
- vellum/client/__init__.py +16 -136
- vellum/client/core/client_wrapper.py +1 -1
- vellum/client/resources/ad_hoc/client.py +14 -104
- vellum/client/resources/metric_definitions/client.py +113 -0
- vellum/client/resources/test_suites/client.py +8 -16
- vellum/client/resources/workflows/client.py +0 -32
- vellum/client/types/__init__.py +2 -0
- vellum/client/types/metric_definition_history_item.py +39 -0
- vellum/types/metric_definition_history_item.py +3 -0
- vellum/workflows/events/node.py +36 -3
- vellum/workflows/events/tests/test_event.py +89 -9
- vellum/workflows/events/types.py +1 -1
- vellum/workflows/nodes/core/inline_subworkflow_node/node.py +1 -0
- vellum/workflows/nodes/core/templating_node/node.py +5 -0
- vellum/workflows/nodes/displayable/api_node/node.py +1 -1
- vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +1 -2
- vellum/workflows/nodes/displayable/code_execution_node/node.py +1 -2
- vellum/workflows/nodes/displayable/code_execution_node/utils.py +13 -2
- vellum/workflows/nodes/displayable/conditional_node/node.py +2 -2
- vellum/workflows/nodes/displayable/inline_prompt_node/node.py +10 -3
- vellum/workflows/nodes/displayable/prompt_deployment_node/node.py +6 -1
- vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +1 -2
- vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py +1 -2
- vellum/workflows/ports/node_ports.py +2 -2
- vellum/workflows/ports/port.py +14 -0
- vellum/workflows/references/__init__.py +2 -0
- vellum/workflows/runner/runner.py +49 -8
- vellum/workflows/runner/types.py +1 -3
- vellum/workflows/state/encoder.py +2 -1
- vellum/workflows/types/__init__.py +5 -0
- vellum/workflows/types/tests/test_utils.py +6 -3
- vellum/workflows/types/utils.py +3 -0
- {vellum_ai-0.10.6.dist-info → vellum_ai-0.10.8.dist-info}/METADATA +1 -1
- {vellum_ai-0.10.6.dist-info → vellum_ai-0.10.8.dist-info}/RECORD +49 -47
- vellum_cli/__init__.py +23 -4
- vellum_cli/pull.py +28 -13
- vellum_cli/tests/test_pull.py +45 -2
- vellum_ee/workflows/display/nodes/base_node_display.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/code_execution_node.py +17 -2
- vellum_ee/workflows/display/nodes/vellum/final_output_node.py +4 -2
- vellum_ee/workflows/display/nodes/vellum/map_node.py +20 -48
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +5 -16
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +11 -8
- vellum_ee/workflows/display/utils/vellum.py +3 -2
- {vellum_ai-0.10.6.dist-info → vellum_ai-0.10.8.dist-info}/LICENSE +0 -0
- {vellum_ai-0.10.6.dist-info → vellum_ai-0.10.8.dist-info}/WHEEL +0 -0
- {vellum_ai-0.10.6.dist-info → vellum_ai-0.10.8.dist-info}/entry_points.txt +0 -0
vellum_cli/pull.py
CHANGED
@@ -7,28 +7,38 @@ from typing import Optional
|
|
7
7
|
from dotenv import load_dotenv
|
8
8
|
|
9
9
|
from vellum.workflows.vellum_client import create_vellum_client
|
10
|
-
from vellum_cli.config import load_vellum_cli_config
|
10
|
+
from vellum_cli.config import WorkflowConfig, load_vellum_cli_config
|
11
11
|
from vellum_cli.logger import load_cli_logger
|
12
12
|
|
13
13
|
|
14
14
|
def pull_command(
|
15
|
-
module: Optional[str]
|
15
|
+
module: Optional[str] = None,
|
16
|
+
workflow_sandbox_id: Optional[str] = None,
|
17
|
+
include_json: Optional[bool] = None,
|
18
|
+
exclude_code: Optional[bool] = None,
|
16
19
|
) -> None:
|
17
20
|
load_dotenv()
|
18
21
|
logger = load_cli_logger()
|
19
22
|
config = load_vellum_cli_config()
|
20
23
|
|
21
|
-
if not config.workflows:
|
22
|
-
raise ValueError("No Workflows found in project to pull.")
|
23
|
-
|
24
|
-
if len(config.workflows) > 1 and not module:
|
25
|
-
raise ValueError("Multiple workflows found in project to pull. Pulling only a single workflow is supported.")
|
26
|
-
|
27
24
|
workflow_config = (
|
28
|
-
next((w for w in config.workflows if w.module == module), None)
|
25
|
+
next((w for w in config.workflows if w.module == module), None)
|
26
|
+
if module
|
27
|
+
else (config.workflows[0] if config.workflows else None)
|
29
28
|
)
|
29
|
+
save_lock_file = False
|
30
30
|
if workflow_config is None:
|
31
|
-
|
31
|
+
if module:
|
32
|
+
raise ValueError(f"No workflow config for '{module}' found in project to pull.")
|
33
|
+
elif workflow_sandbox_id:
|
34
|
+
workflow_config = WorkflowConfig(
|
35
|
+
workflow_sandbox_id=workflow_sandbox_id,
|
36
|
+
module=f"workflow_{workflow_sandbox_id.split('-')[0]}",
|
37
|
+
)
|
38
|
+
config.workflows.append(workflow_config)
|
39
|
+
save_lock_file = True
|
40
|
+
else:
|
41
|
+
raise ValueError("No workflow config found in project to pull from.")
|
32
42
|
|
33
43
|
if not workflow_config.workflow_sandbox_id:
|
34
44
|
raise ValueError("No workflow sandbox ID found in project to pull from.")
|
@@ -36,10 +46,10 @@ def pull_command(
|
|
36
46
|
logger.info(f"Pulling workflow into {workflow_config.module}")
|
37
47
|
client = create_vellum_client()
|
38
48
|
query_parameters = {}
|
39
|
-
if legacy_module:
|
40
|
-
query_parameters["legacyModule"] = legacy_module
|
41
49
|
if include_json:
|
42
50
|
query_parameters["include_json"] = include_json
|
51
|
+
if exclude_code:
|
52
|
+
query_parameters["exclude_code"] = exclude_code
|
43
53
|
|
44
54
|
response = client.workflows.pull(
|
45
55
|
workflow_config.workflow_sandbox_id,
|
@@ -81,6 +91,11 @@ def pull_command(
|
|
81
91
|
target.write(source.read().decode("utf-8"))
|
82
92
|
|
83
93
|
if include_json:
|
84
|
-
logger.warning(
|
94
|
+
logger.warning(
|
95
|
+
"The pulled JSON representation of the Workflow should be used for debugging purposely only. Its schema should be considered unstable and subject to change at any time."
|
96
|
+
)
|
97
|
+
|
98
|
+
if save_lock_file:
|
99
|
+
config.save()
|
85
100
|
|
86
101
|
logger.info(f"Successfully pulled Workflow into {workflow_config.module}")
|
vellum_cli/tests/test_pull.py
CHANGED
@@ -69,8 +69,33 @@ def test_pull(vellum_client, mock_module):
|
|
69
69
|
pull_command(module)
|
70
70
|
|
71
71
|
# THEN the workflow.py file is written to the module directory
|
72
|
-
|
73
|
-
|
72
|
+
workflow_py = os.path.join(temp_dir, *module.split("."), "workflow.py")
|
73
|
+
assert os.path.exists(workflow_py)
|
74
|
+
with open(workflow_py) as f:
|
75
|
+
assert f.read() == "print('hello')"
|
76
|
+
|
77
|
+
|
78
|
+
def test_pull__sandbox_id_with_no_config(vellum_client):
|
79
|
+
# GIVEN a workflow sandbox id
|
80
|
+
workflow_sandbox_id = "87654321-0000-0000-0000-000000000000"
|
81
|
+
|
82
|
+
# AND the workflow pull API call returns a zip file
|
83
|
+
vellum_client.workflows.pull.return_value = iter([zip_file_map({"workflow.py": "print('hello')"})])
|
84
|
+
|
85
|
+
# AND we are currently in a new directory
|
86
|
+
current_dir = os.getcwd()
|
87
|
+
temp_dir = tempfile.mkdtemp()
|
88
|
+
os.chdir(temp_dir)
|
89
|
+
|
90
|
+
# WHEN the user runs the pull command with the workflow sandbox id and no module
|
91
|
+
pull_command(workflow_sandbox_id=workflow_sandbox_id)
|
92
|
+
os.chdir(current_dir)
|
93
|
+
|
94
|
+
# THEN the pull api is called with exclude_code=True
|
95
|
+
vellum_client.workflows.pull.assert_called_once()
|
96
|
+
workflow_py = os.path.join(temp_dir, "workflow_87654321", "workflow.py")
|
97
|
+
assert os.path.exists(workflow_py)
|
98
|
+
with open(workflow_py) as f:
|
74
99
|
assert f.read() == "print('hello')"
|
75
100
|
|
76
101
|
|
@@ -168,3 +193,21 @@ def test_pull__include_json(vellum_client, mock_module):
|
|
168
193
|
vellum_client.workflows.pull.assert_called_once()
|
169
194
|
call_args = vellum_client.workflows.pull.call_args.kwargs
|
170
195
|
assert call_args["request_options"]["additional_query_parameters"] == {"include_json": True}
|
196
|
+
|
197
|
+
|
198
|
+
def test_pull__exclude_code(vellum_client, mock_module):
|
199
|
+
# GIVEN a module on the user's filesystem
|
200
|
+
_, module = mock_module
|
201
|
+
|
202
|
+
# AND the workflow pull API call returns a zip file
|
203
|
+
vellum_client.workflows.pull.return_value = iter(
|
204
|
+
[zip_file_map({"workflow.py": "print('hello')", "workflow.json": "{}"})]
|
205
|
+
)
|
206
|
+
|
207
|
+
# WHEN the user runs the pull command
|
208
|
+
pull_command(module, exclude_code=True)
|
209
|
+
|
210
|
+
# THEN the pull api is called with exclude_code=True
|
211
|
+
vellum_client.workflows.pull.assert_called_once()
|
212
|
+
call_args = vellum_client.workflows.pull.call_args.kwargs
|
213
|
+
assert call_args["request_options"]["additional_query_parameters"] == {"exclude_code": True}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
from functools import cached_property
|
2
2
|
import inspect
|
3
3
|
from uuid import UUID
|
4
|
-
from typing import TYPE_CHECKING, Any, Dict, Generic, Optional, Type, TypeVar, get_args, get_origin
|
4
|
+
from typing import TYPE_CHECKING, Any, Dict, Generic, Optional, Type, TypeVar, cast, get_args, get_origin
|
5
5
|
|
6
6
|
from vellum.workflows.nodes.bases.base import BaseNode
|
7
7
|
from vellum.workflows.nodes.utils import get_wrapped_node, has_wrapped_node
|
@@ -1,5 +1,5 @@
|
|
1
1
|
from uuid import UUID
|
2
|
-
from typing import ClassVar, Generic, Optional, TypeVar
|
2
|
+
from typing import ClassVar, Dict, Generic, Optional, TypeVar
|
3
3
|
|
4
4
|
from vellum.workflows.nodes.displayable.code_execution_node import CodeExecutionNode
|
5
5
|
from vellum.workflows.nodes.displayable.code_execution_node.utils import read_file_from_path
|
@@ -20,6 +20,8 @@ class BaseCodeExecutionNodeDisplay(BaseNodeVellumDisplay[_CodeExecutionNodeType]
|
|
20
20
|
output_id: ClassVar[Optional[UUID]] = None
|
21
21
|
log_output_id: ClassVar[Optional[UUID]] = None
|
22
22
|
|
23
|
+
node_input_ids_by_name: ClassVar[Dict[str, UUID]] = {}
|
24
|
+
|
23
25
|
def serialize(
|
24
26
|
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **kwargs
|
25
27
|
) -> JsonObject:
|
@@ -27,6 +29,19 @@ class BaseCodeExecutionNodeDisplay(BaseNodeVellumDisplay[_CodeExecutionNodeType]
|
|
27
29
|
node_id = self.node_id
|
28
30
|
|
29
31
|
code = read_file_from_path(raise_if_descriptor(node.filepath))
|
32
|
+
code_inputs = raise_if_descriptor(node.code_inputs)
|
33
|
+
|
34
|
+
inputs = [
|
35
|
+
create_node_input(
|
36
|
+
node_id=node_id,
|
37
|
+
input_name=variable_name,
|
38
|
+
value=variable_value,
|
39
|
+
display_context=display_context,
|
40
|
+
input_id=self.node_input_ids_by_name.get(variable_name),
|
41
|
+
)
|
42
|
+
for variable_name, variable_value in code_inputs.items()
|
43
|
+
]
|
44
|
+
|
30
45
|
code_node_input = create_node_input(
|
31
46
|
node_id=node_id,
|
32
47
|
input_name="code",
|
@@ -41,7 +56,7 @@ class BaseCodeExecutionNodeDisplay(BaseNodeVellumDisplay[_CodeExecutionNodeType]
|
|
41
56
|
display_context=display_context,
|
42
57
|
input_id=self.runtime_input_id,
|
43
58
|
)
|
44
|
-
inputs
|
59
|
+
inputs.extend([code_node_input, runtime_node_input])
|
45
60
|
|
46
61
|
packages = raise_if_descriptor(node.packages)
|
47
62
|
|
@@ -1,14 +1,16 @@
|
|
1
1
|
from uuid import UUID
|
2
2
|
from typing import Any, ClassVar, Generic, Optional, TypeVar
|
3
3
|
|
4
|
+
from vellum.workflows.nodes.core.map_node.node import MapNode
|
5
|
+
from vellum.workflows.nodes.displayable.final_output_node import FinalOutputNode
|
6
|
+
from vellum.workflows.references.output import OutputReference
|
7
|
+
from vellum.workflows.types.core import JsonObject
|
4
8
|
from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
|
5
9
|
from vellum_ee.workflows.display.nodes.utils import to_kebab_case
|
6
10
|
from vellum_ee.workflows.display.nodes.vellum.utils import create_node_input
|
7
11
|
from vellum_ee.workflows.display.types import WorkflowDisplayContext
|
8
12
|
from vellum_ee.workflows.display.utils.uuids import uuid4_from_hash
|
9
13
|
from vellum_ee.workflows.display.utils.vellum import infer_vellum_variable_type
|
10
|
-
from vellum.workflows.nodes.displayable.final_output_node import FinalOutputNode
|
11
|
-
from vellum.workflows.types.core import JsonObject
|
12
14
|
|
13
15
|
_FinalOutputNodeType = TypeVar("_FinalOutputNodeType", bound=FinalOutputNode)
|
14
16
|
|
@@ -1,59 +1,32 @@
|
|
1
1
|
from uuid import UUID
|
2
|
-
from typing import
|
2
|
+
from typing import Collection, Dict, Generic, List, Optional, TypeVar, cast
|
3
3
|
|
4
|
-
from vellum import VellumVariable
|
5
4
|
from vellum.workflows.nodes import MapNode
|
6
5
|
from vellum.workflows.types.core import JsonObject
|
7
6
|
from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
|
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
|
10
9
|
from vellum_ee.workflows.display.types import WorkflowDisplayContext
|
11
|
-
from vellum_ee.workflows.display.utils.uuids import uuid4_from_hash
|
12
|
-
from vellum_ee.workflows.display.utils.vellum import infer_vellum_variable_type
|
13
10
|
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
14
11
|
|
15
12
|
_MapNodeType = TypeVar("_MapNodeType", bound=MapNode)
|
16
13
|
|
17
14
|
|
18
15
|
class BaseMapNodeDisplay(BaseNodeVellumDisplay[_MapNodeType], Generic[_MapNodeType]):
|
19
|
-
workflow_input_ids_by_name: ClassVar[Dict[str, UUID]] = {}
|
20
|
-
|
21
16
|
def serialize(
|
22
17
|
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **kwargs
|
23
18
|
) -> JsonObject:
|
24
19
|
node = self._node
|
25
20
|
node_id = self.node_id
|
26
21
|
|
27
|
-
workflow_inputs: List[VellumVariable] = []
|
28
22
|
subworkflow = raise_if_descriptor(node.subworkflow)
|
29
|
-
for descriptor in subworkflow.get_inputs_class():
|
30
|
-
# In WaC it's always 'all_items'
|
31
|
-
# In Vellum it's always 'items'
|
32
|
-
variable_name = descriptor.name if descriptor.name != "all_items" else "items"
|
33
|
-
variable_id = str(
|
34
|
-
self.workflow_input_ids_by_name.get(variable_name)
|
35
|
-
or uuid4_from_hash(f"{self.node_id}|{variable_name}")
|
36
|
-
)
|
37
|
-
workflow_inputs.append(
|
38
|
-
VellumVariable(
|
39
|
-
id=variable_id,
|
40
|
-
key=variable_name,
|
41
|
-
type=infer_vellum_variable_type(descriptor),
|
42
|
-
)
|
43
|
-
)
|
44
|
-
|
45
|
-
items_workflow_input = next(input for input in workflow_inputs if input.key == "items")
|
46
|
-
item_workflow_input = next(input for input in workflow_inputs if input.key == "item")
|
47
|
-
index_workflow_input = next(input for input in workflow_inputs if input.key == "index")
|
48
|
-
|
49
|
-
workflow_outputs = self._generate_workflow_outputs(node)
|
50
23
|
|
51
24
|
items_node_input = create_node_input(
|
52
25
|
node_id=node_id,
|
53
26
|
input_name="items",
|
54
27
|
value=node.items,
|
55
28
|
display_context=display_context,
|
56
|
-
input_id=
|
29
|
+
input_id=self.node_input_ids_by_name.get("items"),
|
57
30
|
)
|
58
31
|
node_inputs = [items_node_input]
|
59
32
|
|
@@ -63,6 +36,19 @@ class BaseMapNodeDisplay(BaseNodeVellumDisplay[_MapNodeType], Generic[_MapNodeTy
|
|
63
36
|
)
|
64
37
|
serialized_subworkflow = subworkflow_display.serialize()
|
65
38
|
|
39
|
+
renamed_input_variables = []
|
40
|
+
for input_variable in cast(List[Dict[str, str]], serialized_subworkflow["input_variables"]):
|
41
|
+
if input_variable["key"] == "all_items":
|
42
|
+
renamed_item = { **input_variable, "key": "items" }
|
43
|
+
renamed_input_variables.append(renamed_item)
|
44
|
+
else:
|
45
|
+
renamed_input_variables.append(input_variable)
|
46
|
+
|
47
|
+
# Note: This must match the items input ID for the map node's node input
|
48
|
+
items_workflow_input_id = next(input_variable["id"] for input_variable in renamed_input_variables if input_variable["key"] == "items")
|
49
|
+
item_workflow_input_id = next(input_variable["id"] for input_variable in renamed_input_variables if input_variable["key"] == "item")
|
50
|
+
index_workflow_input_id = next(input_variable["id"] for input_variable in renamed_input_variables if input_variable["key"] == "index")
|
51
|
+
|
66
52
|
return {
|
67
53
|
"id": str(node_id),
|
68
54
|
"type": "MAP",
|
@@ -74,27 +60,13 @@ class BaseMapNodeDisplay(BaseNodeVellumDisplay[_MapNodeType], Generic[_MapNodeTy
|
|
74
60
|
"target_handle_id": str(self.get_target_handle_id()),
|
75
61
|
"variant": "INLINE",
|
76
62
|
"workflow_raw_data": serialized_subworkflow["workflow_raw_data"],
|
77
|
-
"input_variables":
|
78
|
-
"output_variables": [
|
63
|
+
"input_variables": cast(JsonObject, renamed_input_variables),
|
64
|
+
"output_variables": serialized_subworkflow["output_variables"],
|
79
65
|
"concurrency": raise_if_descriptor(node.concurrency),
|
80
|
-
"items_input_id":
|
81
|
-
"item_input_id":
|
82
|
-
"index_input_id":
|
66
|
+
"items_input_id": items_workflow_input_id,
|
67
|
+
"item_input_id": item_workflow_input_id,
|
68
|
+
"index_input_id": index_workflow_input_id,
|
83
69
|
},
|
84
70
|
"display_data": self.get_display_data().dict(),
|
85
71
|
"definition": self.get_definition().dict(),
|
86
72
|
}
|
87
|
-
|
88
|
-
def _generate_workflow_outputs(
|
89
|
-
self,
|
90
|
-
node: Type[MapNode],
|
91
|
-
) -> List[VellumVariable]:
|
92
|
-
workflow_outputs: List[VellumVariable] = []
|
93
|
-
for output_descriptor in raise_if_descriptor(node.subworkflow).Outputs: # type: ignore[union-attr]
|
94
|
-
node_output_display = self.get_node_output_display(output_descriptor)
|
95
|
-
output_type = infer_vellum_variable_type(output_descriptor)
|
96
|
-
workflow_outputs.append(
|
97
|
-
VellumVariable(id=str(node_output_display.id), key=node_output_display.name, type=output_type)
|
98
|
-
)
|
99
|
-
|
100
|
-
return workflow_outputs
|
@@ -13,30 +13,20 @@ from vellum.workflows.expressions.does_not_equal import DoesNotEqualExpression
|
|
13
13
|
from vellum.workflows.expressions.ends_with import EndsWithExpression
|
14
14
|
from vellum.workflows.expressions.equals import EqualsExpression
|
15
15
|
from vellum.workflows.expressions.greater_than import GreaterThanExpression
|
16
|
-
from vellum.workflows.expressions.greater_than_or_equal_to import
|
17
|
-
GreaterThanOrEqualToExpression,
|
18
|
-
)
|
16
|
+
from vellum.workflows.expressions.greater_than_or_equal_to import GreaterThanOrEqualToExpression
|
19
17
|
from vellum.workflows.expressions.in_ import InExpression
|
20
18
|
from vellum.workflows.expressions.is_not_null import IsNotNullExpression
|
21
19
|
from vellum.workflows.expressions.is_null import IsNullExpression
|
22
20
|
from vellum.workflows.expressions.less_than import LessThanExpression
|
23
|
-
from vellum.workflows.expressions.less_than_or_equal_to import
|
24
|
-
LessThanOrEqualToExpression,
|
25
|
-
)
|
21
|
+
from vellum.workflows.expressions.less_than_or_equal_to import LessThanOrEqualToExpression
|
26
22
|
from vellum.workflows.expressions.not_between import NotBetweenExpression
|
27
23
|
from vellum.workflows.expressions.not_in import NotInExpression
|
28
|
-
from vellum_ee.workflows.display.nodes.base_node_vellum_display import
|
29
|
-
BaseNodeVellumDisplay,
|
30
|
-
)
|
24
|
+
from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
|
31
25
|
from vellum_ee.workflows.display.workflows import VellumWorkflowDisplay
|
32
|
-
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import
|
33
|
-
get_workflow_display,
|
34
|
-
)
|
26
|
+
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
35
27
|
|
36
28
|
from tests.workflows.basic_conditional_node.workflow import CategoryWorkflow
|
37
|
-
from tests.workflows.basic_conditional_node.workflow_with_only_one_conditional_node import
|
38
|
-
create_simple_workflow,
|
39
|
-
)
|
29
|
+
from tests.workflows.basic_conditional_node.workflow_with_only_one_conditional_node import create_simple_workflow
|
40
30
|
|
41
31
|
|
42
32
|
def test_serialize_workflow():
|
@@ -965,7 +955,6 @@ def test_conditional_node_serialize_all_operators_with_lhs_and_rhs(
|
|
965
955
|
|
966
956
|
# AND the conditional node should be what we expect
|
967
957
|
conditional_node = workflow_raw_data["nodes"][1]
|
968
|
-
print(conditional_node)
|
969
958
|
assert not DeepDiff(
|
970
959
|
{
|
971
960
|
"id": "a9143814-6bb0-4cb3-a817-4fc076417121",
|
vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py
CHANGED
@@ -228,15 +228,15 @@ def test_serialize_workflow():
|
|
228
228
|
},
|
229
229
|
},
|
230
230
|
"input_variables": [
|
231
|
-
{"id": "
|
232
|
-
{"id": "
|
233
|
-
{"id": "
|
231
|
+
{"id": "b29bb546-9bc8-4136-857d-8c7a464ba9d4", "key": "item", "type": "JSON", "required": True, "default": None, "extensions": {"color": None}},
|
232
|
+
{"id": "17e7ca49-668f-450d-a792-e1f97d13db67", "key": "index", "type": "NUMBER", "required": True, "default": None, "extensions": {"color": None}},
|
233
|
+
{"id": "d6fc6c7a-235f-4b98-86f3-e258d1198f93", "key": "items", "type": "JSON", "required": True, "default": None, "extensions": {"color": None}},
|
234
234
|
],
|
235
|
-
"output_variables": [{"id": "
|
235
|
+
"output_variables": [{"id": "2a957315-fae0-4366-8a35-f0b315c5eade", "key": "count", "type": "NUMBER"}],
|
236
236
|
"concurrency": None,
|
237
|
-
"items_input_id": "
|
238
|
-
"item_input_id": "
|
239
|
-
"index_input_id": "
|
237
|
+
"items_input_id": "d6fc6c7a-235f-4b98-86f3-e258d1198f93",
|
238
|
+
"item_input_id": "b29bb546-9bc8-4136-857d-8c7a464ba9d4",
|
239
|
+
"index_input_id": "17e7ca49-668f-450d-a792-e1f97d13db67",
|
240
240
|
},
|
241
241
|
"display_data": {"position": {"x": 0.0, "y": 0.0}},
|
242
242
|
"definition": {
|
@@ -288,7 +288,7 @@ def test_serialize_workflow():
|
|
288
288
|
"type": "NODE_OUTPUT",
|
289
289
|
"data": {
|
290
290
|
"node_id": "bf83099a-40df-4445-b90d-1f6f1067ebe3",
|
291
|
-
"output_id": "
|
291
|
+
"output_id": "2a957315-fae0-4366-8a35-f0b315c5eade",
|
292
292
|
},
|
293
293
|
}
|
294
294
|
],
|
@@ -323,6 +323,9 @@ def test_serialize_workflow():
|
|
323
323
|
},
|
324
324
|
},
|
325
325
|
workflow_raw_data["nodes"][2],
|
326
|
+
# TODO: Fix output ID not referencing map node workflow output
|
327
|
+
# https://app.shortcut.com/vellum/story/5667/fix-output-display-reference-on-map-nodes
|
328
|
+
exclude_regex_paths=r"root\['inputs'\]\[0\]\['value'\]\['rules'\]\[0\]\['data'\]\['output_id'\]",
|
326
329
|
)
|
327
330
|
|
328
331
|
# AND each edge should be serialized correctly
|
@@ -4,7 +4,9 @@ import typing
|
|
4
4
|
from typing import Any, List, Union, cast
|
5
5
|
|
6
6
|
from vellum import ChatMessage, SearchResult, SearchResultRequest, VellumVariableType
|
7
|
+
from vellum.client.types.array_vellum_value import ArrayVellumValue
|
7
8
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
9
|
+
from vellum.workflows.nodes.core.map_node.node import MapNodeItemType
|
8
10
|
from vellum.workflows.references import OutputReference, WorkflowInputReference
|
9
11
|
from vellum.workflows.references.execution_count import ExecutionCountReference
|
10
12
|
from vellum.workflows.references.node import NodeReference
|
@@ -45,9 +47,8 @@ def infer_vellum_variable_type(value: Any) -> VellumVariableType:
|
|
45
47
|
raise ValueError(
|
46
48
|
f"Expected NodeReference {descriptor.name} to have an instance pointing to a descriptor"
|
47
49
|
)
|
48
|
-
|
49
50
|
descriptor = descriptor.instance
|
50
|
-
|
51
|
+
|
51
52
|
inferred_type = primitive_type_to_vellum_variable_type(descriptor)
|
52
53
|
else:
|
53
54
|
vellum_variable_value = primitive_to_vellum_value(value)
|
File without changes
|
File without changes
|
File without changes
|