vellum-ai 1.6.4__py3-none-any.whl → 1.7.0__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 (35) hide show
  1. vellum/__init__.py +2 -0
  2. vellum/client/core/client_wrapper.py +2 -2
  3. vellum/client/reference.md +81 -0
  4. vellum/client/resources/container_images/client.py +8 -2
  5. vellum/client/resources/container_images/raw_client.py +8 -0
  6. vellum/client/resources/workflows/client.py +81 -0
  7. vellum/client/resources/workflows/raw_client.py +85 -0
  8. vellum/client/types/__init__.py +2 -0
  9. vellum/client/types/workflow_resolved_state.py +31 -0
  10. vellum/types/workflow_resolved_state.py +3 -0
  11. vellum/workflows/descriptors/base.py +3 -0
  12. vellum/workflows/errors/types.py +1 -0
  13. vellum/workflows/inputs/base.py +4 -1
  14. vellum/workflows/inputs/tests/test_inputs.py +21 -0
  15. vellum/workflows/runner/runner.py +16 -0
  16. vellum/workflows/workflows/base.py +2 -0
  17. {vellum_ai-1.6.4.dist-info → vellum_ai-1.7.0.dist-info}/METADATA +1 -1
  18. {vellum_ai-1.6.4.dist-info → vellum_ai-1.7.0.dist-info}/RECORD +35 -33
  19. vellum_ee/assets/node-definitions.json +157 -12
  20. vellum_ee/workflows/display/exceptions.py +2 -6
  21. vellum_ee/workflows/display/nodes/vellum/code_execution_node.py +1 -1
  22. vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py +1 -1
  23. vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py +11 -4
  24. vellum_ee/workflows/display/nodes/vellum/search_node.py +4 -4
  25. vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py +11 -4
  26. vellum_ee/workflows/display/nodes/vellum/tests/test_code_execution_node.py +1 -1
  27. vellum_ee/workflows/display/utils/exceptions.py +19 -0
  28. vellum_ee/workflows/display/utils/expressions.py +19 -11
  29. vellum_ee/workflows/display/utils/vellum.py +7 -1
  30. vellum_ee/workflows/display/workflows/base_workflow_display.py +2 -2
  31. vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +54 -1
  32. vellum_ee/workflows/tests/test_server.py +41 -0
  33. {vellum_ai-1.6.4.dist-info → vellum_ai-1.7.0.dist-info}/LICENSE +0 -0
  34. {vellum_ai-1.6.4.dist-info → vellum_ai-1.7.0.dist-info}/WHEEL +0 -0
  35. {vellum_ai-1.6.4.dist-info → vellum_ai-1.7.0.dist-info}/entry_points.txt +0 -0
@@ -15,7 +15,7 @@ from vellum.workflows.references.lazy import LazyReference
15
15
  from vellum.workflows.references.node import NodeReference
16
16
  from vellum.workflows.references.vellum_secret import VellumSecretReference
17
17
  from vellum.workflows.utils.vellum_variables import primitive_type_to_vellum_variable_type
18
- from vellum_ee.workflows.display.utils.exceptions import UnsupportedSerializationException
18
+ from vellum_ee.workflows.display.utils.exceptions import InvalidInputReferenceError, UnsupportedSerializationException
19
19
  from vellum_ee.workflows.display.utils.expressions import get_child_descriptor
20
20
 
21
21
  if TYPE_CHECKING:
@@ -124,6 +124,12 @@ def create_node_input_value_pointer_rule(
124
124
  child_descriptor = get_child_descriptor(value, display_context)
125
125
  return create_node_input_value_pointer_rule(child_descriptor, display_context)
126
126
  if isinstance(value, WorkflowInputReference):
127
+ if value not in display_context.global_workflow_input_displays:
128
+ raise InvalidInputReferenceError(
129
+ message=f"Inputs class '{value.inputs_class.__qualname__}' has no attribute '{value.name}'",
130
+ inputs_class_name=value.inputs_class.__qualname__,
131
+ attribute_name=value.name,
132
+ )
127
133
  workflow_input_display = display_context.global_workflow_input_displays[value]
128
134
  return InputVariablePointer(data=InputVariableData(input_variable_id=str(workflow_input_display.id)))
129
135
  if isinstance(value, VellumSecretReference):
@@ -39,7 +39,6 @@ from vellum_ee.workflows.display.base import (
39
39
  WorkflowOutputDisplay,
40
40
  )
41
41
  from vellum_ee.workflows.display.editor.types import NodeDisplayData, NodeDisplayPosition
42
- from vellum_ee.workflows.display.exceptions import NodeValidationError
43
42
  from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
44
43
  from vellum_ee.workflows.display.nodes.get_node_display_class import get_node_display_class
45
44
  from vellum_ee.workflows.display.nodes.types import NodeOutputDisplay, PortDisplay
@@ -57,6 +56,7 @@ from vellum_ee.workflows.display.types import (
57
56
  WorkflowOutputDisplays,
58
57
  )
59
58
  from vellum_ee.workflows.display.utils.auto_layout import auto_layout_nodes
59
+ from vellum_ee.workflows.display.utils.exceptions import UserFacingException
60
60
  from vellum_ee.workflows.display.utils.expressions import serialize_value
61
61
  from vellum_ee.workflows.display.utils.registry import register_workflow_display_class
62
62
  from vellum_ee.workflows.display.utils.vellum import infer_vellum_variable_type
@@ -203,7 +203,7 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
203
203
  self.display_context.add_validation_error(validation_error)
204
204
 
205
205
  serialized_node = node_display.serialize(self.display_context)
206
- except (NotImplementedError, NodeValidationError) as e:
206
+ except (NotImplementedError, UserFacingException) as e:
207
207
  self.display_context.add_error(e)
208
208
  self.display_context.add_invalid_node(node)
209
209
  continue
@@ -14,7 +14,7 @@ from vellum.workflows.state.base import BaseState
14
14
  from vellum.workflows.types.core import JsonObject
15
15
  from vellum.workflows.workflows.base import BaseWorkflow
16
16
  from vellum_ee.workflows.display.editor.types import NodeDisplayData, NodeDisplayPosition
17
- from vellum_ee.workflows.display.nodes import BaseNodeDisplay
17
+ from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
18
18
  from vellum_ee.workflows.display.nodes.vellum.retry_node import BaseRetryNodeDisplay
19
19
  from vellum_ee.workflows.display.nodes.vellum.try_node import BaseTryNodeDisplay
20
20
  from vellum_ee.workflows.display.types import WorkflowDisplayContext
@@ -997,3 +997,56 @@ def test_serialize_workflow__with_complete_node_failure_prunes_edges():
997
997
  node_types = [node["type"] for node in data["workflow_raw_data"]["nodes"]]
998
998
  assert "ENTRYPOINT" in node_types
999
999
  assert "GENERIC" in node_types # This is the WorkingNode that should still be serialized
1000
+
1001
+
1002
+ def test_serialize_workflow__node_with_invalid_input_reference():
1003
+ """Test that serialization captures errors when nodes reference a non-existent input attribute."""
1004
+
1005
+ # GIVEN a workflow with defined inputs
1006
+ class Inputs(BaseInputs):
1007
+ valid_input: str
1008
+
1009
+ # AND a templating node that references a non-existent input
1010
+ class MyTemplatingNode(TemplatingNode):
1011
+ class Outputs(TemplatingNode.Outputs):
1012
+ pass
1013
+
1014
+ template = "valid: {{ valid_input }}, invalid: {{ invalid_ref }}"
1015
+ inputs = {
1016
+ "valid_input": Inputs.valid_input,
1017
+ "invalid_ref": Inputs.invalid_ref,
1018
+ }
1019
+
1020
+ # AND a base node that also references the non-existent input
1021
+ class MyBaseNode(BaseNode):
1022
+ invalid_ref = Inputs.invalid_ref
1023
+
1024
+ class Outputs(BaseNode.Outputs):
1025
+ result: str
1026
+
1027
+ def run(self) -> BaseNode.Outputs:
1028
+ return self.Outputs(result="done")
1029
+
1030
+ class MyBaseNodeDisplay(BaseNodeDisplay[MyBaseNode]):
1031
+ __serializable_inputs__ = {MyBaseNode.invalid_ref}
1032
+
1033
+ # WHEN we create a workflow with both nodes and serialize with dry_run=True
1034
+ class MyWorkflow(BaseWorkflow[Inputs, BaseState]):
1035
+ graph = MyTemplatingNode >> MyBaseNode
1036
+
1037
+ workflow_display = get_workflow_display(workflow_class=MyWorkflow, dry_run=True)
1038
+ serialized = workflow_display.serialize()
1039
+
1040
+ # THEN the serialization should succeed without raising an exception
1041
+ assert serialized is not None
1042
+ assert "workflow_raw_data" in serialized
1043
+
1044
+ errors = list(workflow_display.display_context.errors)
1045
+ assert len(errors) > 0
1046
+
1047
+ # AND the error messages should reference the missing attribute
1048
+ error_messages = [str(e) for e in errors]
1049
+ assert any("invalid_ref" in msg for msg in error_messages)
1050
+
1051
+ invalid_nodes = list(workflow_display.display_context.invalid_nodes)
1052
+ assert len(invalid_nodes) >= 2
@@ -1,3 +1,4 @@
1
+ import pytest
1
2
  import sys
2
3
  from uuid import uuid4
3
4
  from typing import Type, cast
@@ -6,6 +7,7 @@ from vellum.client.core.pydantic_utilities import UniversalBaseModel
6
7
  from vellum.client.types.code_executor_response import CodeExecutorResponse
7
8
  from vellum.client.types.number_vellum_value import NumberVellumValue
8
9
  from vellum.workflows import BaseWorkflow
10
+ from vellum.workflows.exceptions import WorkflowInitializationException
9
11
  from vellum.workflows.nodes import BaseNode
10
12
  from vellum.workflows.state.context import WorkflowContext
11
13
  from vellum.workflows.utils.uuids import generate_workflow_deployment_prefix
@@ -499,6 +501,45 @@ class MapNodeWorkflow(BaseWorkflow):
499
501
  assert event.body.outputs == {"results": [1.0, 1.0, 1.0]}
500
502
 
501
503
 
504
+ def test_load_from_module__syntax_error_in_node_file():
505
+ """
506
+ Tests that a syntax error in a node file raises WorkflowInitializationException with user-facing message.
507
+ """
508
+ # GIVEN a workflow module with a node file containing a syntax error (missing colon)
509
+ files = {
510
+ "__init__.py": "",
511
+ "workflow.py": """\
512
+ from vellum.workflows import BaseWorkflow
513
+ from .nodes.broken_node import BrokenNode
514
+
515
+ class Workflow(BaseWorkflow):
516
+ graph = BrokenNode
517
+ """,
518
+ "nodes/__init__.py": "",
519
+ "nodes/broken_node.py": """\
520
+ from vellum.workflows.nodes import BaseNode
521
+
522
+ class BrokenNode(BaseNode) # Missing colon
523
+ \"\"\"This node has a syntax error.\"\"\"
524
+ """,
525
+ }
526
+
527
+ namespace = str(uuid4())
528
+
529
+ # AND the virtual file loader is registered
530
+ sys.meta_path.append(VirtualFileFinder(files, namespace))
531
+
532
+ # WHEN we attempt to load the workflow
533
+ # THEN it should raise WorkflowInitializationException
534
+ with pytest.raises(WorkflowInitializationException) as exc_info:
535
+ BaseWorkflow.load_from_module(namespace)
536
+
537
+ # AND the error message should be user-friendly
538
+ error_message = str(exc_info.value)
539
+ assert "Failed to load workflow module:" in error_message
540
+ assert "invalid syntax" in error_message or "expected ':'" in error_message
541
+
542
+
502
543
  def test_serialize_module__tool_calling_node_with_single_tool():
503
544
  """Test that serialize_module works with a tool calling node that has a single tool."""
504
545