vellum-ai 0.14.68__py3-none-any.whl → 0.14.70__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 +4 -0
- vellum/client/core/client_wrapper.py +1 -1
- vellum/client/types/__init__.py +4 -0
- vellum/client/types/fast_embed_vectorizer_baai_bge_small_en_v_15.py +23 -0
- vellum/client/types/fast_embed_vectorizer_baai_bge_small_en_v_15_request.py +23 -0
- vellum/client/types/folder_entity_document_index_data.py +2 -0
- vellum/client/types/indexing_config_vectorizer.py +2 -0
- vellum/client/types/indexing_config_vectorizer_request.py +2 -0
- vellum/types/fast_embed_vectorizer_baai_bge_small_en_v_15.py +3 -0
- vellum/types/fast_embed_vectorizer_baai_bge_small_en_v_15_request.py +3 -0
- vellum/workflows/environment/__init__.py +2 -1
- vellum/workflows/environment/environment.py +5 -1
- vellum/workflows/nodes/displayable/bases/search_node.py +15 -3
- vellum/workflows/nodes/displayable/tests/test_search_node_error_handling.py +215 -0
- vellum/workflows/nodes/experimental/tool_calling_node/tests/test_node.py +77 -1
- vellum/workflows/nodes/experimental/tool_calling_node/utils.py +2 -2
- vellum/workflows/references/environment_variable.py +2 -3
- {vellum_ai-0.14.68.dist-info → vellum_ai-0.14.70.dist-info}/METADATA +1 -1
- {vellum_ai-0.14.68.dist-info → vellum_ai-0.14.70.dist-info}/RECORD +54 -45
- vellum_cli/__init__.py +5 -2
- vellum_cli/image_push.py +24 -1
- vellum_cli/tests/test_image_push.py +103 -12
- vellum_ee/workflows/display/nodes/base_node_display.py +1 -1
- vellum_ee/workflows/display/nodes/utils.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/api_node.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/code_execution_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/conditional_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/error_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/final_output_node.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/guardrail_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py +4 -4
- vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py +9 -1
- vellum_ee/workflows/display/nodes/vellum/map_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/merge_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/note_node.py +1 -0
- vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/retry_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/search_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/templating_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/tests/test_inline_subworkflow_node.py +88 -0
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +16 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_prompt_node_serialization.py +81 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +9 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_serialization.py +59 -297
- vellum_ee/workflows/display/utils/auto_layout.py +130 -0
- vellum_ee/workflows/display/utils/expressions.py +7 -0
- vellum_ee/workflows/display/utils/tests/__init__.py +0 -0
- vellum_ee/workflows/display/utils/tests/test_auto_layout.py +56 -0
- vellum_ee/workflows/display/workflows/base_workflow_display.py +15 -10
- vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +41 -0
- {vellum_ai-0.14.68.dist-info → vellum_ai-0.14.70.dist-info}/LICENSE +0 -0
- {vellum_ai-0.14.68.dist-info → vellum_ai-0.14.70.dist-info}/WHEEL +0 -0
- {vellum_ai-0.14.68.dist-info → vellum_ai-0.14.70.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
from uuid import uuid4
|
2
|
+
|
3
|
+
from vellum_ee.workflows.display.base import EdgeDisplay
|
4
|
+
from vellum_ee.workflows.display.editor.types import NodeDisplayData, NodeDisplayPosition
|
5
|
+
from vellum_ee.workflows.display.utils.auto_layout import auto_layout_nodes
|
6
|
+
|
7
|
+
|
8
|
+
def test_auto_layout_basic():
|
9
|
+
"""Test basic auto layout functionality with a simple linear graph."""
|
10
|
+
nodes = [
|
11
|
+
("node1", NodeDisplayData(position=NodeDisplayPosition(x=0, y=0), width=100, height=80)),
|
12
|
+
("node2", NodeDisplayData(position=NodeDisplayPosition(x=0, y=0), width=120, height=90)),
|
13
|
+
("node3", NodeDisplayData(position=NodeDisplayPosition(x=0, y=0), width=110, height=85)),
|
14
|
+
]
|
15
|
+
|
16
|
+
edges = [
|
17
|
+
("node1", "node2", EdgeDisplay(id=uuid4())),
|
18
|
+
("node2", "node3", EdgeDisplay(id=uuid4())),
|
19
|
+
]
|
20
|
+
|
21
|
+
positioned_nodes = auto_layout_nodes(nodes, edges)
|
22
|
+
|
23
|
+
node_positions = {node_id: data.position for node_id, data in positioned_nodes}
|
24
|
+
|
25
|
+
assert node_positions["node1"].x < node_positions["node2"].x
|
26
|
+
assert node_positions["node2"].x < node_positions["node3"].x
|
27
|
+
|
28
|
+
|
29
|
+
def test_auto_layout_parallel_branches():
|
30
|
+
"""Test auto layout with parallel branches."""
|
31
|
+
nodes = [
|
32
|
+
("start", NodeDisplayData(position=NodeDisplayPosition(x=0, y=0), width=100, height=80)),
|
33
|
+
("branch1", NodeDisplayData(position=NodeDisplayPosition(x=0, y=0), width=100, height=80)),
|
34
|
+
("branch2", NodeDisplayData(position=NodeDisplayPosition(x=0, y=0), width=100, height=80)),
|
35
|
+
("end", NodeDisplayData(position=NodeDisplayPosition(x=0, y=0), width=100, height=80)),
|
36
|
+
]
|
37
|
+
|
38
|
+
edges = [
|
39
|
+
("start", "branch1", EdgeDisplay(id=uuid4())),
|
40
|
+
("start", "branch2", EdgeDisplay(id=uuid4())),
|
41
|
+
("branch1", "end", EdgeDisplay(id=uuid4())),
|
42
|
+
("branch2", "end", EdgeDisplay(id=uuid4())),
|
43
|
+
]
|
44
|
+
|
45
|
+
positioned_nodes = auto_layout_nodes(nodes, edges)
|
46
|
+
|
47
|
+
node_positions = {node_id: data.position for node_id, data in positioned_nodes}
|
48
|
+
|
49
|
+
assert node_positions["start"].x < node_positions["branch1"].x
|
50
|
+
assert node_positions["start"].x < node_positions["branch2"].x
|
51
|
+
|
52
|
+
assert node_positions["branch1"].x == node_positions["branch2"].x
|
53
|
+
assert node_positions["branch1"].x < node_positions["end"].x
|
54
|
+
|
55
|
+
assert node_positions["branch1"].x < node_positions["end"].x
|
56
|
+
assert node_positions["branch2"].x < node_positions["end"].x
|
@@ -200,16 +200,21 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
|
|
200
200
|
raise ValueError(f"Failed to serialize output '{workflow_output.name}': {str(e)}") from e
|
201
201
|
|
202
202
|
source_node_display: Optional[BaseNodeDisplay]
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
203
|
+
if not node_input.value.rules:
|
204
|
+
source_node_display = None
|
205
|
+
else:
|
206
|
+
first_rule = node_input.value.rules[0]
|
207
|
+
if first_rule.type == "NODE_OUTPUT":
|
208
|
+
source_node_id = UUID(first_rule.data.node_id)
|
209
|
+
try:
|
210
|
+
source_node_display = [
|
211
|
+
node_display
|
212
|
+
for node_display in self.display_context.node_displays.values()
|
213
|
+
if node_display.node_id == source_node_id
|
214
|
+
][0]
|
215
|
+
except IndexError:
|
216
|
+
source_node_display = None
|
217
|
+
else:
|
213
218
|
source_node_display = None
|
214
219
|
|
215
220
|
synthetic_target_handle_id = str(
|
@@ -787,3 +787,44 @@ def test_serialize_workflow__dict_reference():
|
|
787
787
|
},
|
788
788
|
],
|
789
789
|
}
|
790
|
+
|
791
|
+
|
792
|
+
def test_serialize_workflow__empty_rules_indexerror():
|
793
|
+
"""Test that workflow serialization handles dictionary key access correctly."""
|
794
|
+
|
795
|
+
# GIVEN a node with dictionary output
|
796
|
+
class StartNode(BaseNode):
|
797
|
+
class Outputs(BaseNode.Outputs):
|
798
|
+
data: dict = {"key": "value"}
|
799
|
+
|
800
|
+
# AND a workflow that references dictionary key access in its outputs
|
801
|
+
class MyWorkflow(BaseWorkflow):
|
802
|
+
graph = StartNode
|
803
|
+
|
804
|
+
class Outputs(BaseWorkflow.Outputs):
|
805
|
+
# This dictionary key access should be handled gracefully
|
806
|
+
problematic_output = StartNode.Outputs.data["bar"]
|
807
|
+
|
808
|
+
# WHEN we serialize the workflow
|
809
|
+
workflow_display = get_workflow_display(workflow_class=MyWorkflow)
|
810
|
+
result: dict = workflow_display.serialize()
|
811
|
+
|
812
|
+
assert result is not None
|
813
|
+
assert "output_variables" in result
|
814
|
+
assert "workflow_raw_data" in result
|
815
|
+
|
816
|
+
# AND the workflow output should contain the dictionary key access
|
817
|
+
output_variables = result["output_variables"]
|
818
|
+
assert len(output_variables) == 1
|
819
|
+
assert output_variables[0]["key"] == "problematic_output"
|
820
|
+
|
821
|
+
# AND the workflow raw data should contain nodes including terminal node
|
822
|
+
workflow_raw_data = result["workflow_raw_data"]
|
823
|
+
assert "nodes" in workflow_raw_data
|
824
|
+
nodes = workflow_raw_data["nodes"]
|
825
|
+
|
826
|
+
assert len(nodes) >= 3
|
827
|
+
|
828
|
+
terminal_nodes = [node for node in nodes if node.get("type") == "TERMINAL"]
|
829
|
+
assert len(terminal_nodes) == 1
|
830
|
+
assert terminal_nodes[0]["data"]["name"] == "problematic_output"
|
File without changes
|
File without changes
|
File without changes
|