vellum-ai 1.2.5__py3-none-any.whl → 1.3.1__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 (48) hide show
  1. vellum/__init__.py +8 -0
  2. vellum/client/README.md +1 -1
  3. vellum/client/core/client_wrapper.py +2 -2
  4. vellum/client/reference.md +0 -9
  5. vellum/client/resources/workflow_sandboxes/client.py +0 -12
  6. vellum/client/resources/workflow_sandboxes/raw_client.py +2 -10
  7. vellum/client/types/__init__.py +8 -0
  8. vellum/client/types/deployment_read.py +5 -5
  9. vellum/client/types/slim_deployment_read.py +5 -5
  10. vellum/client/types/slim_workflow_deployment.py +5 -5
  11. vellum/client/types/workflow_deployment_read.py +5 -5
  12. vellum/client/types/workflow_request_audio_input_request.py +30 -0
  13. vellum/client/types/workflow_request_document_input_request.py +30 -0
  14. vellum/client/types/workflow_request_image_input_request.py +30 -0
  15. vellum/client/types/workflow_request_input_request.py +8 -0
  16. vellum/client/types/workflow_request_video_input_request.py +30 -0
  17. vellum/types/workflow_request_audio_input_request.py +3 -0
  18. vellum/types/workflow_request_document_input_request.py +3 -0
  19. vellum/types/workflow_request_image_input_request.py +3 -0
  20. vellum/types/workflow_request_video_input_request.py +3 -0
  21. vellum/workflows/events/types.py +6 -1
  22. vellum/workflows/events/workflow.py +9 -2
  23. vellum/workflows/integrations/tests/test_mcp_service.py +106 -1
  24. vellum/workflows/nodes/__init__.py +2 -0
  25. vellum/workflows/nodes/displayable/__init__.py +2 -0
  26. vellum/workflows/nodes/displayable/tool_calling_node/utils.py +11 -0
  27. vellum/workflows/nodes/displayable/web_search_node/__init__.py +3 -0
  28. vellum/workflows/nodes/displayable/web_search_node/node.py +133 -0
  29. vellum/workflows/nodes/displayable/web_search_node/tests/__init__.py +0 -0
  30. vellum/workflows/nodes/displayable/web_search_node/tests/test_node.py +319 -0
  31. vellum/workflows/resolvers/base.py +3 -2
  32. vellum/workflows/resolvers/resolver.py +62 -7
  33. vellum/workflows/resolvers/tests/test_resolver.py +79 -7
  34. vellum/workflows/resolvers/types.py +11 -0
  35. vellum/workflows/runner/runner.py +49 -1
  36. vellum/workflows/state/context.py +41 -7
  37. vellum/workflows/utils/zip.py +46 -0
  38. vellum/workflows/workflows/base.py +10 -0
  39. {vellum_ai-1.2.5.dist-info → vellum_ai-1.3.1.dist-info}/METADATA +1 -1
  40. {vellum_ai-1.2.5.dist-info → vellum_ai-1.3.1.dist-info}/RECORD +48 -34
  41. vellum_cli/tests/test_init.py +7 -24
  42. vellum_cli/tests/test_pull.py +27 -52
  43. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +7 -33
  44. vellum_ee/workflows/display/utils/events.py +3 -0
  45. vellum_ee/workflows/tests/test_server.py +115 -0
  46. {vellum_ai-1.2.5.dist-info → vellum_ai-1.3.1.dist-info}/LICENSE +0 -0
  47. {vellum_ai-1.2.5.dist-info → vellum_ai-1.3.1.dist-info}/WHEEL +0 -0
  48. {vellum_ai-1.2.5.dist-info → vellum_ai-1.3.1.dist-info}/entry_points.txt +0 -0
@@ -142,41 +142,15 @@ def test_serialize_node__lazy_reference(serialize_node):
142
142
  attr: str = LazyReference(lambda: ConstantValueReference("hello"))
143
143
 
144
144
  serialized_node = serialize_node(LazyReferenceGenericNode)
145
+ attributes = serialized_node["attributes"]
145
146
 
146
- assert not DeepDiff(
147
+ assert attributes == [
147
148
  {
148
- "id": "3d6bfe3b-263a-40a6-8a05-98288e9559a4",
149
- "label": "Lazy Reference Generic Node",
150
- "type": "GENERIC",
151
- "display_data": {"position": {"x": 0.0, "y": 0.0}},
152
- "base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
153
- "definition": {
154
- "name": "LazyReferenceGenericNode",
155
- "module": [
156
- "vellum_ee",
157
- "workflows",
158
- "display",
159
- "tests",
160
- "workflow_serialization",
161
- "generic_nodes",
162
- "test_attributes_serialization",
163
- ],
164
- },
165
- "trigger": {"id": "14ec4d19-13e5-4db3-94fa-4e15274bffc7", "merge_behavior": "AWAIT_ATTRIBUTES"},
166
- "ports": [{"id": "2dba7224-a376-4780-8414-2b50601f9283", "name": "default", "type": "DEFAULT"}],
167
- "adornments": None,
168
- "attributes": [
169
- {
170
- "id": "7ae37eb4-18c8-49e1-b5ac-6369ce7ed5dd",
171
- "name": "attr",
172
- "value": {"type": "CONSTANT_VALUE", "value": {"type": "STRING", "value": "hello"}},
173
- }
174
- ],
175
- "outputs": [],
176
- },
177
- serialized_node,
178
- ignore_order=True,
179
- )
149
+ "id": "7ae37eb4-18c8-49e1-b5ac-6369ce7ed5dd",
150
+ "name": "attr",
151
+ "value": {"type": "CONSTANT_VALUE", "value": {"type": "STRING", "value": "hello"}},
152
+ }
153
+ ]
180
154
 
181
155
 
182
156
  def test_serialize_node__lazy_reference_with_string():
@@ -26,6 +26,9 @@ def _should_mark_workflow_dynamic(event: WorkflowExecutionInitiatedEvent) -> boo
26
26
 
27
27
 
28
28
  def event_enricher(event: WorkflowExecutionInitiatedEvent) -> WorkflowExecutionInitiatedEvent:
29
+ if event.name != "workflow.execution.initiated":
30
+ return event
31
+
29
32
  workflow_definition = event.body.workflow_definition
30
33
  workflow_display = get_workflow_display(
31
34
  workflow_class=workflow_definition,
@@ -9,6 +9,7 @@ from vellum.workflows import BaseWorkflow
9
9
  from vellum.workflows.nodes import BaseNode
10
10
  from vellum.workflows.state.context import WorkflowContext
11
11
  from vellum.workflows.utils.uuids import generate_workflow_deployment_prefix
12
+ from vellum.workflows.utils.zip import zip_file_map
12
13
  from vellum_ee.workflows.display.workflows.base_workflow_display import BaseWorkflowDisplay
13
14
  from vellum_ee.workflows.server.virtual_file_loader import VirtualFileFinder
14
15
 
@@ -661,3 +662,117 @@ __all__ = ["TestNode"]
661
662
 
662
663
  # AND the method should return a workflow (not None) - this will pass once implemented
663
664
  assert event.name == "workflow.execution.fulfilled"
665
+
666
+
667
+ def test_resolve_workflow_deployment__uses_pull_api_with_inputs_deployment_name(vellum_client):
668
+ """
669
+ Test that resolve_workflow_deployment uses the pull API to fetch subworkflow files
670
+ when the deployment name comes from Inputs.deployment_name.
671
+ """
672
+ # GIVEN a deployment name and release tag
673
+ deployment_name = "test_deployment"
674
+ release_tag = "LATEST"
675
+
676
+ test_node_code = """
677
+ from vellum.workflows.nodes.bases.base import BaseNode
678
+ from vellum.workflows.outputs import BaseOutputs
679
+
680
+ class TestNode(BaseNode):
681
+ template = "Hello"
682
+
683
+ class Outputs(BaseOutputs):
684
+ result: str
685
+
686
+ def run(self):
687
+ return self.Outputs(result="Hello, {template}")
688
+ """
689
+
690
+ mock_workflow_code = """
691
+ from vellum.workflows import BaseWorkflow
692
+ from .nodes.test_node import TestNode
693
+
694
+ class ResolvedWorkflow(BaseWorkflow):
695
+ graph = TestNode
696
+ """
697
+
698
+ inputs_code = """
699
+ from vellum.workflows.inputs import BaseInputs
700
+
701
+ class Inputs(BaseInputs):
702
+ deployment_name: str
703
+ """
704
+
705
+ parent_workflow_code = """
706
+ from vellum.workflows import BaseWorkflow
707
+ from .inputs import Inputs
708
+ from .nodes.subworkflow_deployment_node import TestSubworkflowDeploymentNode
709
+ from vellum.workflows.state import BaseState
710
+
711
+ class ParentWorkflow(BaseWorkflow[Inputs, BaseState]):
712
+ graph = TestSubworkflowDeploymentNode
713
+ """
714
+
715
+ parent_node_code = """
716
+ from vellum.workflows.nodes import SubworkflowDeploymentNode
717
+ from vellum.workflows.outputs import BaseOutputs
718
+ from ..inputs import Inputs
719
+
720
+ class TestSubworkflowDeploymentNode(SubworkflowDeploymentNode):
721
+ deployment = Inputs.deployment_name
722
+
723
+ class Outputs(BaseOutputs):
724
+ result: str
725
+
726
+ subworkflow_inputs = {"message": "test"}
727
+ """
728
+
729
+ subworkflow_files = {
730
+ "__init__.py": "",
731
+ "workflow.py": mock_workflow_code,
732
+ "nodes/__init__.py": """
733
+ from .test_node import TestNode
734
+
735
+ __all__ = ["TestNode"]
736
+ """,
737
+ "nodes/test_node.py": test_node_code,
738
+ }
739
+
740
+ parent_files = {
741
+ "__init__.py": "",
742
+ "inputs.py": inputs_code,
743
+ "workflow.py": parent_workflow_code,
744
+ "nodes/__init__.py": """
745
+ from .subworkflow_deployment_node import TestSubworkflowDeploymentNode
746
+
747
+ __all__ = ["TestSubworkflowDeploymentNode"]
748
+ """,
749
+ "nodes/subworkflow_deployment_node.py": parent_node_code,
750
+ }
751
+
752
+ namespace = str(uuid4())
753
+
754
+ # AND the virtual file loader is registered for the parent workflow
755
+ finder = VirtualFileFinder(parent_files, namespace)
756
+ sys.meta_path.append(finder)
757
+
758
+ vellum_client.workflows.pull.return_value = iter([zip_file_map(subworkflow_files)])
759
+
760
+ # WHEN we execute the root workflow with the mocked client
761
+ Workflow = BaseWorkflow.load_from_module(namespace)
762
+ Inputs = Workflow.get_inputs_class()
763
+
764
+ workflow = Workflow(context=WorkflowContext(namespace=namespace, generated_files=parent_files))
765
+ final_event = workflow.run(inputs=Inputs(deployment_name=deployment_name))
766
+
767
+ # THEN the method should return a workflow (not None) - this will pass once implemented
768
+ assert final_event.name == "workflow.execution.fulfilled", final_event
769
+
770
+ # AND the pull API should have been called with the correct deployment name, release tag, and version
771
+ args, kwargs = vellum_client.workflows.pull.call_args
772
+ assert args[0] == deployment_name
773
+ assert kwargs["release_tag"] == release_tag
774
+ assert kwargs["version"].startswith(">=")
775
+ assert ".0.0,<=" in kwargs["version"]
776
+
777
+ # AND the X-Vellum-Always-Success header should be included for graceful error handling
778
+ assert kwargs["request_options"]["additional_headers"]["X-Vellum-Always-Success"] == "true"