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.
- vellum/__init__.py +8 -0
- vellum/client/README.md +1 -1
- vellum/client/core/client_wrapper.py +2 -2
- vellum/client/reference.md +0 -9
- vellum/client/resources/workflow_sandboxes/client.py +0 -12
- vellum/client/resources/workflow_sandboxes/raw_client.py +2 -10
- vellum/client/types/__init__.py +8 -0
- vellum/client/types/deployment_read.py +5 -5
- vellum/client/types/slim_deployment_read.py +5 -5
- vellum/client/types/slim_workflow_deployment.py +5 -5
- vellum/client/types/workflow_deployment_read.py +5 -5
- vellum/client/types/workflow_request_audio_input_request.py +30 -0
- vellum/client/types/workflow_request_document_input_request.py +30 -0
- vellum/client/types/workflow_request_image_input_request.py +30 -0
- vellum/client/types/workflow_request_input_request.py +8 -0
- vellum/client/types/workflow_request_video_input_request.py +30 -0
- vellum/types/workflow_request_audio_input_request.py +3 -0
- vellum/types/workflow_request_document_input_request.py +3 -0
- vellum/types/workflow_request_image_input_request.py +3 -0
- vellum/types/workflow_request_video_input_request.py +3 -0
- vellum/workflows/events/types.py +6 -1
- vellum/workflows/events/workflow.py +9 -2
- vellum/workflows/integrations/tests/test_mcp_service.py +106 -1
- vellum/workflows/nodes/__init__.py +2 -0
- vellum/workflows/nodes/displayable/__init__.py +2 -0
- vellum/workflows/nodes/displayable/tool_calling_node/utils.py +11 -0
- vellum/workflows/nodes/displayable/web_search_node/__init__.py +3 -0
- vellum/workflows/nodes/displayable/web_search_node/node.py +133 -0
- vellum/workflows/nodes/displayable/web_search_node/tests/__init__.py +0 -0
- vellum/workflows/nodes/displayable/web_search_node/tests/test_node.py +319 -0
- vellum/workflows/resolvers/base.py +3 -2
- vellum/workflows/resolvers/resolver.py +62 -7
- vellum/workflows/resolvers/tests/test_resolver.py +79 -7
- vellum/workflows/resolvers/types.py +11 -0
- vellum/workflows/runner/runner.py +49 -1
- vellum/workflows/state/context.py +41 -7
- vellum/workflows/utils/zip.py +46 -0
- vellum/workflows/workflows/base.py +10 -0
- {vellum_ai-1.2.5.dist-info → vellum_ai-1.3.1.dist-info}/METADATA +1 -1
- {vellum_ai-1.2.5.dist-info → vellum_ai-1.3.1.dist-info}/RECORD +48 -34
- vellum_cli/tests/test_init.py +7 -24
- vellum_cli/tests/test_pull.py +27 -52
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +7 -33
- vellum_ee/workflows/display/utils/events.py +3 -0
- vellum_ee/workflows/tests/test_server.py +115 -0
- {vellum_ai-1.2.5.dist-info → vellum_ai-1.3.1.dist-info}/LICENSE +0 -0
- {vellum_ai-1.2.5.dist-info → vellum_ai-1.3.1.dist-info}/WHEEL +0 -0
- {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
|
147
|
+
assert attributes == [
|
147
148
|
{
|
148
|
-
"id": "
|
149
|
-
"
|
150
|
-
"type": "
|
151
|
-
|
152
|
-
|
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"
|
File without changes
|
File without changes
|
File without changes
|