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.
Files changed (54) hide show
  1. vellum/__init__.py +4 -0
  2. vellum/client/core/client_wrapper.py +1 -1
  3. vellum/client/types/__init__.py +4 -0
  4. vellum/client/types/fast_embed_vectorizer_baai_bge_small_en_v_15.py +23 -0
  5. vellum/client/types/fast_embed_vectorizer_baai_bge_small_en_v_15_request.py +23 -0
  6. vellum/client/types/folder_entity_document_index_data.py +2 -0
  7. vellum/client/types/indexing_config_vectorizer.py +2 -0
  8. vellum/client/types/indexing_config_vectorizer_request.py +2 -0
  9. vellum/types/fast_embed_vectorizer_baai_bge_small_en_v_15.py +3 -0
  10. vellum/types/fast_embed_vectorizer_baai_bge_small_en_v_15_request.py +3 -0
  11. vellum/workflows/environment/__init__.py +2 -1
  12. vellum/workflows/environment/environment.py +5 -1
  13. vellum/workflows/nodes/displayable/bases/search_node.py +15 -3
  14. vellum/workflows/nodes/displayable/tests/test_search_node_error_handling.py +215 -0
  15. vellum/workflows/nodes/experimental/tool_calling_node/tests/test_node.py +77 -1
  16. vellum/workflows/nodes/experimental/tool_calling_node/utils.py +2 -2
  17. vellum/workflows/references/environment_variable.py +2 -3
  18. {vellum_ai-0.14.68.dist-info → vellum_ai-0.14.70.dist-info}/METADATA +1 -1
  19. {vellum_ai-0.14.68.dist-info → vellum_ai-0.14.70.dist-info}/RECORD +54 -45
  20. vellum_cli/__init__.py +5 -2
  21. vellum_cli/image_push.py +24 -1
  22. vellum_cli/tests/test_image_push.py +103 -12
  23. vellum_ee/workflows/display/nodes/base_node_display.py +1 -1
  24. vellum_ee/workflows/display/nodes/utils.py +2 -2
  25. vellum_ee/workflows/display/nodes/vellum/api_node.py +2 -2
  26. vellum_ee/workflows/display/nodes/vellum/code_execution_node.py +1 -1
  27. vellum_ee/workflows/display/nodes/vellum/conditional_node.py +1 -1
  28. vellum_ee/workflows/display/nodes/vellum/error_node.py +1 -1
  29. vellum_ee/workflows/display/nodes/vellum/final_output_node.py +2 -2
  30. vellum_ee/workflows/display/nodes/vellum/guardrail_node.py +1 -1
  31. vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py +4 -4
  32. vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py +9 -1
  33. vellum_ee/workflows/display/nodes/vellum/map_node.py +1 -1
  34. vellum_ee/workflows/display/nodes/vellum/merge_node.py +1 -1
  35. vellum_ee/workflows/display/nodes/vellum/note_node.py +1 -0
  36. vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py +1 -1
  37. vellum_ee/workflows/display/nodes/vellum/retry_node.py +1 -1
  38. vellum_ee/workflows/display/nodes/vellum/search_node.py +1 -1
  39. vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py +1 -1
  40. vellum_ee/workflows/display/nodes/vellum/templating_node.py +1 -1
  41. vellum_ee/workflows/display/nodes/vellum/tests/test_inline_subworkflow_node.py +88 -0
  42. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +16 -0
  43. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_prompt_node_serialization.py +81 -0
  44. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +9 -1
  45. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_serialization.py +59 -297
  46. vellum_ee/workflows/display/utils/auto_layout.py +130 -0
  47. vellum_ee/workflows/display/utils/expressions.py +7 -0
  48. vellum_ee/workflows/display/utils/tests/__init__.py +0 -0
  49. vellum_ee/workflows/display/utils/tests/test_auto_layout.py +56 -0
  50. vellum_ee/workflows/display/workflows/base_workflow_display.py +15 -10
  51. vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +41 -0
  52. {vellum_ai-0.14.68.dist-info → vellum_ai-0.14.70.dist-info}/LICENSE +0 -0
  53. {vellum_ai-0.14.68.dist-info → vellum_ai-0.14.70.dist-info}/WHEEL +0 -0
  54. {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
- first_rule = node_input.value.rules[0]
204
- if first_rule.type == "NODE_OUTPUT":
205
- source_node_id = UUID(first_rule.data.node_id)
206
- try:
207
- source_node_display = [
208
- node_display
209
- for node_display in self.display_context.node_displays.values()
210
- if node_display.node_id == source_node_id
211
- ][0]
212
- except IndexError:
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"