vellum-ai 1.11.2__py3-none-any.whl → 1.13.5__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.
Potentially problematic release.
This version of vellum-ai might be problematic. Click here for more details.
- vellum/__init__.py +18 -0
- vellum/client/README.md +1 -1
- vellum/client/core/client_wrapper.py +2 -2
- vellum/client/core/force_multipart.py +4 -2
- vellum/client/core/http_response.py +1 -1
- vellum/client/core/pydantic_utilities.py +7 -4
- vellum/client/errors/too_many_requests_error.py +1 -2
- vellum/client/reference.md +677 -76
- vellum/client/resources/container_images/client.py +299 -0
- vellum/client/resources/container_images/raw_client.py +286 -0
- vellum/client/resources/documents/client.py +20 -10
- vellum/client/resources/documents/raw_client.py +20 -10
- vellum/client/resources/events/raw_client.py +4 -4
- vellum/client/resources/integration_auth_configs/client.py +2 -0
- vellum/client/resources/integration_auth_configs/raw_client.py +2 -0
- vellum/client/resources/integration_providers/client.py +28 -2
- vellum/client/resources/integration_providers/raw_client.py +24 -0
- vellum/client/resources/integrations/client.py +52 -4
- vellum/client/resources/integrations/raw_client.py +61 -0
- vellum/client/resources/workflow_deployments/client.py +156 -0
- vellum/client/resources/workflow_deployments/raw_client.py +334 -0
- vellum/client/resources/workflows/client.py +212 -8
- vellum/client/resources/workflows/raw_client.py +343 -6
- vellum/client/types/__init__.py +18 -0
- vellum/client/types/api_actor_type_enum.py +1 -1
- vellum/client/types/check_workflow_execution_status_error.py +21 -0
- vellum/client/types/check_workflow_execution_status_response.py +29 -0
- vellum/client/types/code_execution_package_request.py +21 -0
- vellum/client/types/composio_execute_tool_request.py +5 -0
- vellum/client/types/composio_tool_definition.py +1 -0
- vellum/client/types/container_image_build_config.py +1 -0
- vellum/client/types/container_image_container_image_tag.py +1 -0
- vellum/client/types/dataset_row_push_request.py +3 -0
- vellum/client/types/document_document_to_document_index.py +1 -0
- vellum/client/types/integration_name.py +24 -0
- vellum/client/types/node_execution_fulfilled_body.py +1 -0
- vellum/client/types/node_execution_log_body.py +24 -0
- vellum/client/types/node_execution_log_event.py +47 -0
- vellum/client/types/prompt_deployment_release_prompt_deployment.py +1 -0
- vellum/client/types/runner_config_request.py +24 -0
- vellum/client/types/severity_enum.py +5 -0
- vellum/client/types/slim_composio_tool_definition.py +1 -0
- vellum/client/types/slim_document_document_to_document_index.py +2 -0
- vellum/client/types/type_checker_enum.py +5 -0
- vellum/client/types/vellum_audio.py +5 -1
- vellum/client/types/vellum_audio_request.py +5 -1
- vellum/client/types/vellum_document.py +5 -1
- vellum/client/types/vellum_document_request.py +5 -1
- vellum/client/types/vellum_image.py +5 -1
- vellum/client/types/vellum_image_request.py +5 -1
- vellum/client/types/vellum_node_execution_event.py +2 -0
- vellum/client/types/vellum_variable.py +5 -0
- vellum/client/types/vellum_variable_extensions.py +1 -0
- vellum/client/types/vellum_variable_type.py +1 -0
- vellum/client/types/vellum_video.py +5 -1
- vellum/client/types/vellum_video_request.py +5 -1
- vellum/client/types/workflow_deployment_release_workflow_deployment.py +1 -0
- vellum/client/types/workflow_event.py +2 -0
- vellum/client/types/workflow_execution_fulfilled_body.py +1 -0
- vellum/client/types/workflow_result_event_output_data_array.py +1 -1
- vellum/client/types/workflow_result_event_output_data_chat_history.py +1 -1
- vellum/client/types/workflow_result_event_output_data_error.py +1 -1
- vellum/client/types/workflow_result_event_output_data_function_call.py +1 -1
- vellum/client/types/workflow_result_event_output_data_json.py +1 -1
- vellum/client/types/workflow_result_event_output_data_number.py +1 -1
- vellum/client/types/workflow_result_event_output_data_search_results.py +1 -1
- vellum/client/types/workflow_result_event_output_data_string.py +1 -1
- vellum/client/types/workflow_sandbox_execute_node_response.py +8 -0
- vellum/plugins/vellum_mypy.py +37 -2
- vellum/types/check_workflow_execution_status_error.py +3 -0
- vellum/types/check_workflow_execution_status_response.py +3 -0
- vellum/types/code_execution_package_request.py +3 -0
- vellum/types/node_execution_log_body.py +3 -0
- vellum/types/node_execution_log_event.py +3 -0
- vellum/types/runner_config_request.py +3 -0
- vellum/types/severity_enum.py +3 -0
- vellum/types/type_checker_enum.py +3 -0
- vellum/types/workflow_sandbox_execute_node_response.py +3 -0
- vellum/utils/files/mixin.py +26 -0
- vellum/utils/files/tests/test_mixin.py +62 -0
- vellum/utils/tests/test_vellum_client.py +95 -0
- vellum/utils/uuid.py +19 -2
- vellum/utils/vellum_client.py +10 -3
- vellum/workflows/__init__.py +7 -1
- vellum/workflows/descriptors/base.py +86 -0
- vellum/workflows/descriptors/tests/test_utils.py +9 -0
- vellum/workflows/errors/tests/__init__.py +0 -0
- vellum/workflows/errors/tests/test_types.py +52 -0
- vellum/workflows/errors/types.py +1 -0
- vellum/workflows/events/node.py +24 -0
- vellum/workflows/events/tests/test_event.py +123 -0
- vellum/workflows/events/types.py +2 -1
- vellum/workflows/events/workflow.py +28 -2
- vellum/workflows/expressions/add.py +3 -0
- vellum/workflows/expressions/tests/test_add.py +24 -0
- vellum/workflows/graph/graph.py +26 -5
- vellum/workflows/graph/tests/test_graph.py +228 -1
- vellum/workflows/inputs/base.py +22 -6
- vellum/workflows/inputs/dataset_row.py +121 -16
- vellum/workflows/inputs/tests/test_inputs.py +3 -3
- vellum/workflows/integrations/tests/test_vellum_integration_service.py +84 -0
- vellum/workflows/integrations/vellum_integration_service.py +12 -1
- vellum/workflows/loaders/base.py +2 -0
- vellum/workflows/nodes/bases/base.py +37 -16
- vellum/workflows/nodes/bases/tests/test_base_node.py +104 -1
- vellum/workflows/nodes/core/inline_subworkflow_node/node.py +1 -0
- vellum/workflows/nodes/core/inline_subworkflow_node/tests/test_node.py +1 -1
- vellum/workflows/nodes/core/map_node/node.py +7 -5
- vellum/workflows/nodes/core/map_node/tests/test_node.py +33 -0
- vellum/workflows/nodes/core/retry_node/node.py +1 -0
- vellum/workflows/nodes/core/try_node/node.py +1 -0
- vellum/workflows/nodes/displayable/api_node/node.py +3 -2
- vellum/workflows/nodes/displayable/api_node/tests/test_api_node.py +38 -0
- vellum/workflows/nodes/displayable/bases/api_node/node.py +1 -1
- vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py +18 -1
- vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py +109 -2
- vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +13 -2
- vellum/workflows/nodes/displayable/code_execution_node/node.py +9 -15
- vellum/workflows/nodes/displayable/code_execution_node/tests/test_node.py +65 -24
- vellum/workflows/nodes/displayable/code_execution_node/utils.py +3 -0
- vellum/workflows/nodes/displayable/final_output_node/node.py +24 -69
- vellum/workflows/nodes/displayable/final_output_node/tests/test_node.py +53 -3
- vellum/workflows/nodes/displayable/note_node/node.py +4 -1
- vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +16 -5
- vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py +47 -0
- vellum/workflows/nodes/displayable/tool_calling_node/node.py +74 -34
- vellum/workflows/nodes/displayable/tool_calling_node/tests/test_node.py +204 -8
- vellum/workflows/nodes/displayable/tool_calling_node/utils.py +92 -71
- vellum/workflows/nodes/mocks.py +47 -213
- vellum/workflows/nodes/tests/test_mocks.py +0 -177
- vellum/workflows/nodes/utils.py +23 -8
- vellum/workflows/outputs/base.py +36 -3
- vellum/workflows/references/environment_variable.py +1 -11
- vellum/workflows/references/lazy.py +8 -0
- vellum/workflows/references/state_value.py +24 -1
- vellum/workflows/references/tests/test_lazy.py +58 -0
- vellum/workflows/references/trigger.py +8 -3
- vellum/workflows/references/workflow_input.py +8 -0
- vellum/workflows/resolvers/resolver.py +13 -3
- vellum/workflows/resolvers/tests/test_resolver.py +31 -0
- vellum/workflows/runner/runner.py +159 -14
- vellum/workflows/runner/tests/__init__.py +0 -0
- vellum/workflows/runner/tests/test_runner.py +170 -0
- vellum/workflows/sandbox.py +7 -8
- vellum/workflows/state/base.py +89 -30
- vellum/workflows/state/context.py +74 -3
- vellum/workflows/state/tests/test_state.py +269 -1
- vellum/workflows/tests/test_dataset_row.py +8 -7
- vellum/workflows/tests/test_sandbox.py +97 -8
- vellum/workflows/triggers/__init__.py +2 -1
- vellum/workflows/triggers/base.py +160 -28
- vellum/workflows/triggers/chat_message.py +141 -0
- vellum/workflows/triggers/integration.py +12 -0
- vellum/workflows/triggers/manual.py +3 -1
- vellum/workflows/triggers/schedule.py +3 -1
- vellum/workflows/triggers/tests/test_chat_message.py +257 -0
- vellum/workflows/types/core.py +18 -0
- vellum/workflows/types/definition.py +6 -13
- vellum/workflows/types/generics.py +12 -0
- vellum/workflows/types/tests/test_utils.py +12 -0
- vellum/workflows/types/utils.py +32 -2
- vellum/workflows/types/workflow_metadata.py +124 -0
- vellum/workflows/utils/functions.py +152 -16
- vellum/workflows/utils/pydantic_schema.py +19 -1
- vellum/workflows/utils/tests/test_functions.py +123 -8
- vellum/workflows/utils/tests/test_validate.py +79 -0
- vellum/workflows/utils/tests/test_vellum_variables.py +62 -2
- vellum/workflows/utils/uuids.py +90 -0
- vellum/workflows/utils/validate.py +108 -0
- vellum/workflows/utils/vellum_variables.py +96 -16
- vellum/workflows/workflows/base.py +177 -35
- vellum/workflows/workflows/tests/test_base_workflow.py +51 -0
- {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/METADATA +6 -1
- {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/RECORD +274 -227
- vellum_cli/__init__.py +21 -0
- vellum_cli/config.py +16 -2
- vellum_cli/pull.py +2 -0
- vellum_cli/push.py +23 -10
- vellum_cli/tests/conftest.py +8 -13
- vellum_cli/tests/test_image_push.py +4 -11
- vellum_cli/tests/test_pull.py +83 -68
- vellum_cli/tests/test_push.py +251 -2
- vellum_ee/assets/node-definitions.json +225 -12
- vellum_ee/scripts/generate_node_definitions.py +15 -3
- vellum_ee/workflows/display/base.py +4 -3
- vellum_ee/workflows/display/nodes/base_node_display.py +44 -11
- vellum_ee/workflows/display/nodes/tests/test_base_node_display.py +93 -0
- vellum_ee/workflows/display/nodes/types.py +1 -0
- vellum_ee/workflows/display/nodes/vellum/__init__.py +0 -2
- vellum_ee/workflows/display/nodes/vellum/base_adornment_node.py +5 -2
- vellum_ee/workflows/display/nodes/vellum/code_execution_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py +10 -2
- vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py +17 -14
- vellum_ee/workflows/display/nodes/vellum/map_node.py +2 -0
- vellum_ee/workflows/display/nodes/vellum/note_node.py +18 -3
- vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py +37 -14
- vellum_ee/workflows/display/nodes/vellum/tests/test_code_execution_node.py +62 -2
- vellum_ee/workflows/display/nodes/vellum/tests/test_final_output_node.py +136 -0
- vellum_ee/workflows/display/nodes/vellum/tests/test_note_node.py +44 -7
- vellum_ee/workflows/display/nodes/vellum/tests/test_prompt_node.py +5 -13
- vellum_ee/workflows/display/nodes/vellum/tests/test_subworkflow_deployment_node.py +27 -17
- vellum_ee/workflows/display/nodes/vellum/tests/test_tool_calling_node.py +145 -22
- vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py +107 -2
- vellum_ee/workflows/display/nodes/vellum/utils.py +54 -12
- vellum_ee/workflows/display/tests/test_base_workflow_display.py +13 -16
- vellum_ee/workflows/display/tests/test_json_schema_validation.py +190 -0
- vellum_ee/workflows/display/tests/test_mocks.py +912 -0
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +14 -2
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +109 -0
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py +3 -0
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py +187 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py +34 -325
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +42 -393
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +13 -315
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_default_state_serialization.py +2 -122
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py +24 -115
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py +4 -93
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py +7 -80
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_prompt_node_serialization.py +9 -101
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +77 -308
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +62 -324
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +3 -82
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py +4 -142
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_serialization.py +1 -61
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_set_state_node_serialization.py +4 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py +205 -134
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py +34 -146
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py +2 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_composio_serialization.py +8 -6
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_serialization.py +137 -266
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_tool_wrapper_serialization.py +84 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_mcp_serialization.py +55 -16
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_serialization.py +15 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_tool_wrapper_serialization.py +71 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_vellum_integration_serialization.py +119 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_workflow_deployment_serialization.py +1 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py +0 -2
- vellum_ee/workflows/display/tests/workflow_serialization/test_chat_message_dict_reference_serialization.py +22 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_chat_message_trigger_serialization.py +412 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_code_tool_node_reference_error.py +106 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py +9 -41
- vellum_ee/workflows/display/tests/workflow_serialization/test_duplicate_trigger_name_validation.py +208 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_final_output_node_not_referenced_by_workflow_outputs.py +45 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_infinite_loop_validation.py +66 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_int_input_serialization.py +40 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_integration_trigger_serialization.py +8 -14
- vellum_ee/workflows/display/tests/workflow_serialization/test_integration_trigger_validation.py +173 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_integration_trigger_with_entrypoint_node_id.py +16 -13
- vellum_ee/workflows/display/tests/workflow_serialization/test_list_vellum_document_serialization.py +5 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_manual_trigger_serialization.py +12 -2
- vellum_ee/workflows/display/tests/workflow_serialization/test_multi_trigger_same_node_serialization.py +111 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_no_triggers_no_entrypoint_validation.py +64 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_partial_workflow_meta_display_override.py +55 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_sandbox_dataset_mocks_serialization.py +268 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_sandbox_invalid_pdf_data_url.py +49 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_sandbox_validation_errors.py +112 -0
- vellum_ee/workflows/display/tests/workflow_serialization/test_scheduled_trigger_serialization.py +25 -16
- vellum_ee/workflows/display/tests/workflow_serialization/test_terminal_node_in_unused_graphs_serialization.py +53 -0
- vellum_ee/workflows/display/utils/exceptions.py +34 -0
- vellum_ee/workflows/display/utils/expressions.py +463 -52
- vellum_ee/workflows/display/utils/metadata.py +98 -33
- vellum_ee/workflows/display/utils/tests/test_metadata.py +31 -0
- vellum_ee/workflows/display/utils/triggers.py +153 -0
- vellum_ee/workflows/display/utils/vellum.py +59 -5
- vellum_ee/workflows/display/workflows/base_workflow_display.py +656 -254
- vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py +26 -0
- vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +77 -29
- vellum_ee/workflows/server/namespaces.py +18 -0
- vellum_ee/workflows/tests/test_display_meta.py +2 -0
- vellum_ee/workflows/tests/test_serialize_module.py +174 -7
- vellum_ee/workflows/tests/test_server.py +0 -3
- vellum_ee/workflows/display/nodes/vellum/function_node.py +0 -14
- {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/LICENSE +0 -0
- {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/WHEEL +0 -0
- {vellum_ai-1.11.2.dist-info → vellum_ai-1.13.5.dist-info}/entry_points.txt +0 -0
|
@@ -105,7 +105,13 @@ def test_serialize_node__retry(serialize_node):
|
|
|
105
105
|
}
|
|
106
106
|
],
|
|
107
107
|
"outputs": [
|
|
108
|
-
{
|
|
108
|
+
{
|
|
109
|
+
"id": "78eece53-8a20-40a1-8a86-ffebe256282b",
|
|
110
|
+
"name": "output",
|
|
111
|
+
"type": "STRING",
|
|
112
|
+
"value": None,
|
|
113
|
+
"schema": {"type": "string"},
|
|
114
|
+
}
|
|
109
115
|
],
|
|
110
116
|
},
|
|
111
117
|
serialized_node,
|
|
@@ -197,7 +203,13 @@ def test_serialize_node__try(serialize_node):
|
|
|
197
203
|
}
|
|
198
204
|
],
|
|
199
205
|
"outputs": [
|
|
200
|
-
{
|
|
206
|
+
{
|
|
207
|
+
"id": "d8d0c9a8-0804-4b43-a874-28a7e7d6aec8",
|
|
208
|
+
"name": "output",
|
|
209
|
+
"type": "STRING",
|
|
210
|
+
"value": None,
|
|
211
|
+
"schema": {"type": "string"},
|
|
212
|
+
}
|
|
201
213
|
],
|
|
202
214
|
},
|
|
203
215
|
serialized_node,
|
|
@@ -190,6 +190,115 @@ def test_serialize_node__lazy_reference_with_string():
|
|
|
190
190
|
]
|
|
191
191
|
|
|
192
192
|
|
|
193
|
+
def test_serialize_node__lazy_reference_workflow_output():
|
|
194
|
+
"""Test that LazyReference to workflow output serializes as WORKFLOW_OUTPUT type."""
|
|
195
|
+
|
|
196
|
+
# GIVEN a node with a LazyReference to a workflow output
|
|
197
|
+
class NodeWithWorkflowOutputReference(BaseNode):
|
|
198
|
+
workflow_output_ref = LazyReference(lambda: TestWorkflow.Outputs.final_result)
|
|
199
|
+
|
|
200
|
+
class TestNode(BaseNode):
|
|
201
|
+
class Outputs(BaseNode.Outputs):
|
|
202
|
+
result: str = "test result"
|
|
203
|
+
|
|
204
|
+
# AND a workflow that defines an output
|
|
205
|
+
class TestWorkflow(BaseWorkflow):
|
|
206
|
+
graph = NodeWithWorkflowOutputReference >> TestNode
|
|
207
|
+
|
|
208
|
+
class Outputs(BaseWorkflow.Outputs):
|
|
209
|
+
final_result = TestNode.Outputs.result
|
|
210
|
+
|
|
211
|
+
# WHEN the node is serialized in the context of the workflow
|
|
212
|
+
workflow_display = get_workflow_display(workflow_class=TestWorkflow)
|
|
213
|
+
serialized_workflow: dict = workflow_display.serialize()
|
|
214
|
+
|
|
215
|
+
# THEN the node should properly serialize the workflow output reference
|
|
216
|
+
node_with_lazy_reference = next(
|
|
217
|
+
node
|
|
218
|
+
for node in serialized_workflow["workflow_raw_data"]["nodes"]
|
|
219
|
+
if node["id"] == str(NodeWithWorkflowOutputReference.__id__)
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
# AND the workflow output reference should serialize as WORKFLOW_OUTPUT type
|
|
223
|
+
assert len(node_with_lazy_reference["attributes"]) == 1
|
|
224
|
+
attr = node_with_lazy_reference["attributes"][0]
|
|
225
|
+
assert attr["name"] == "workflow_output_ref"
|
|
226
|
+
assert attr["value"]["type"] == "WORKFLOW_OUTPUT"
|
|
227
|
+
|
|
228
|
+
# AND the output_variable_id should match the workflow output
|
|
229
|
+
workflow_output = next(
|
|
230
|
+
output for output in serialized_workflow["output_variables"] if output["key"] == "final_result"
|
|
231
|
+
)
|
|
232
|
+
assert attr["value"]["output_variable_id"] == workflow_output["id"]
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def test_serialize_node__lazy_reference_workflow_output_with_string():
|
|
236
|
+
"""Test that string-based LazyReference to workflow output serializes as WORKFLOW_OUTPUT type."""
|
|
237
|
+
|
|
238
|
+
# GIVEN a node with a string-based LazyReference to a workflow output
|
|
239
|
+
class NodeWithWorkflowOutputReference(BaseNode):
|
|
240
|
+
workflow_output_ref = LazyReference[str]("StringWorkflow.Outputs.final_result")
|
|
241
|
+
|
|
242
|
+
class TestNode(BaseNode):
|
|
243
|
+
class Outputs(BaseNode.Outputs):
|
|
244
|
+
result: str = "test result"
|
|
245
|
+
|
|
246
|
+
# AND a workflow that defines an output
|
|
247
|
+
class StringWorkflow(BaseWorkflow):
|
|
248
|
+
graph = NodeWithWorkflowOutputReference >> TestNode
|
|
249
|
+
|
|
250
|
+
class Outputs(BaseWorkflow.Outputs):
|
|
251
|
+
final_result = TestNode.Outputs.result
|
|
252
|
+
|
|
253
|
+
# WHEN the node is serialized in the context of the workflow
|
|
254
|
+
workflow_display = get_workflow_display(workflow_class=StringWorkflow)
|
|
255
|
+
serialized_workflow: dict = workflow_display.serialize()
|
|
256
|
+
|
|
257
|
+
# THEN the node should properly serialize the workflow output reference
|
|
258
|
+
node_with_lazy_reference = next(
|
|
259
|
+
node
|
|
260
|
+
for node in serialized_workflow["workflow_raw_data"]["nodes"]
|
|
261
|
+
if node["id"] == str(NodeWithWorkflowOutputReference.__id__)
|
|
262
|
+
)
|
|
263
|
+
|
|
264
|
+
# AND the workflow output reference should serialize as WORKFLOW_OUTPUT type
|
|
265
|
+
assert len(node_with_lazy_reference["attributes"]) == 1
|
|
266
|
+
attr = node_with_lazy_reference["attributes"][0]
|
|
267
|
+
assert attr["name"] == "workflow_output_ref"
|
|
268
|
+
assert attr["value"]["type"] == "WORKFLOW_OUTPUT"
|
|
269
|
+
|
|
270
|
+
# AND the output_variable_id should match the workflow output
|
|
271
|
+
workflow_output = next(
|
|
272
|
+
output for output in serialized_workflow["output_variables"] if output["key"] == "final_result"
|
|
273
|
+
)
|
|
274
|
+
assert attr["value"]["output_variable_id"] == workflow_output["id"]
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def test_serialize_node__lazy_reference_with_string__class_not_found():
|
|
278
|
+
"""Test that InvalidOutputReferenceError is added to display context when the referenced class is not found."""
|
|
279
|
+
|
|
280
|
+
# GIVEN a node with a string-based LazyReference to a non-existent class
|
|
281
|
+
class NodeWithInvalidReference(BaseNode):
|
|
282
|
+
invalid_ref = LazyReference[str]("NonExistentClass.Outputs.result")
|
|
283
|
+
|
|
284
|
+
# AND a workflow that contains the node
|
|
285
|
+
class TestWorkflow(BaseWorkflow):
|
|
286
|
+
graph = NodeWithInvalidReference
|
|
287
|
+
|
|
288
|
+
# WHEN we try to serialize the workflow
|
|
289
|
+
workflow_display = get_workflow_display(workflow_class=TestWorkflow)
|
|
290
|
+
workflow_display.serialize()
|
|
291
|
+
|
|
292
|
+
# THEN the error should be added to the display context
|
|
293
|
+
errors = list(workflow_display.display_context.errors)
|
|
294
|
+
assert len(errors) == 1
|
|
295
|
+
|
|
296
|
+
# AND the error message should mention the class that could not be found
|
|
297
|
+
error_message = str(errors[0])
|
|
298
|
+
assert "NonExistentClass" in error_message
|
|
299
|
+
assert "Could not find node or workflow class" in error_message
|
|
300
|
+
|
|
301
|
+
|
|
193
302
|
def test_serialize_node__workflow_input(serialize_node):
|
|
194
303
|
class WorkflowInputGenericNode(BaseNode):
|
|
195
304
|
attr: str = Inputs.input
|
vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py
CHANGED
|
@@ -50,6 +50,7 @@ def test_serialize_node__annotated_output(serialize_node):
|
|
|
50
50
|
"name": "output",
|
|
51
51
|
"type": "NUMBER",
|
|
52
52
|
"value": None,
|
|
53
|
+
"schema": {"type": "integer"},
|
|
53
54
|
}
|
|
54
55
|
],
|
|
55
56
|
},
|
|
@@ -102,6 +103,7 @@ def test_serialize_node__workflow_input(serialize_node):
|
|
|
102
103
|
"type": "WORKFLOW_INPUT",
|
|
103
104
|
"input_variable_id": str(input_id),
|
|
104
105
|
},
|
|
106
|
+
"schema": {"type": "string"},
|
|
105
107
|
}
|
|
106
108
|
],
|
|
107
109
|
},
|
|
@@ -168,6 +170,7 @@ def test_serialize_node__node_output_reference(serialize_node):
|
|
|
168
170
|
"node_id": "40fcba1f-9b25-4fed-8f15-a2fd80ff85a1",
|
|
169
171
|
"node_output_id": str(node_output_id),
|
|
170
172
|
},
|
|
173
|
+
"schema": {"type": "string"},
|
|
171
174
|
}
|
|
172
175
|
],
|
|
173
176
|
},
|
vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
from uuid import uuid4
|
|
2
|
+
from typing import cast
|
|
2
3
|
|
|
3
4
|
from deepdiff import DeepDiff
|
|
4
5
|
|
|
6
|
+
from vellum.workflows.descriptors.base import BaseDescriptor
|
|
5
7
|
from vellum.workflows.inputs.base import BaseInputs
|
|
6
8
|
from vellum.workflows.nodes.bases.base import BaseNode
|
|
7
9
|
from vellum.workflows.ports.port import Port
|
|
8
10
|
from vellum.workflows.references.vellum_secret import VellumSecretReference
|
|
9
|
-
from
|
|
11
|
+
from vellum.workflows.types.core import JsonArray, JsonObject
|
|
12
|
+
from vellum_ee.workflows.display.base import WorkflowInputsDisplay, WorkflowMetaDisplay
|
|
13
|
+
from vellum_ee.workflows.display.editor.types import NodeDisplayData
|
|
10
14
|
from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
|
|
15
|
+
from vellum_ee.workflows.display.nodes.get_node_display_class import get_node_display_class
|
|
11
16
|
from vellum_ee.workflows.display.nodes.types import NodeOutputDisplay
|
|
17
|
+
from vellum_ee.workflows.display.types import WorkflowDisplayContext
|
|
18
|
+
from vellum_ee.workflows.display.utils.exceptions import UnsupportedSerializationException
|
|
19
|
+
from vellum_ee.workflows.display.workflows.base_workflow_display import BaseWorkflowDisplay
|
|
12
20
|
|
|
13
21
|
|
|
14
22
|
class Inputs(BaseInputs):
|
|
@@ -1001,6 +1009,133 @@ def test_serialize_node__or_then_and(serialize_node):
|
|
|
1001
1009
|
)
|
|
1002
1010
|
|
|
1003
1011
|
|
|
1012
|
+
def test_serialize_node__blank(serialize_node):
|
|
1013
|
+
"""
|
|
1014
|
+
Tests that a node with an is_blank() port condition serializes correctly.
|
|
1015
|
+
"""
|
|
1016
|
+
|
|
1017
|
+
# GIVEN a node with an is_blank() port condition
|
|
1018
|
+
class BlankGenericNode(BaseNode):
|
|
1019
|
+
|
|
1020
|
+
class Ports(BaseNode.Ports):
|
|
1021
|
+
if_branch = Port.on_if(Inputs.input.is_blank())
|
|
1022
|
+
|
|
1023
|
+
input_id = uuid4()
|
|
1024
|
+
|
|
1025
|
+
# WHEN we serialize the node
|
|
1026
|
+
serialized_node = serialize_node(
|
|
1027
|
+
node_class=BlankGenericNode, global_workflow_input_displays={Inputs.input: WorkflowInputsDisplay(id=input_id)}
|
|
1028
|
+
)
|
|
1029
|
+
|
|
1030
|
+
# THEN the serialized node should have the correct structure with a UNARY_EXPRESSION and "blank" operator
|
|
1031
|
+
assert not DeepDiff(
|
|
1032
|
+
{
|
|
1033
|
+
"id": "a9067b0e-6c3b-4ed0-8b0a-a4eb861f75a8",
|
|
1034
|
+
"label": "Blank Generic Node",
|
|
1035
|
+
"type": "GENERIC",
|
|
1036
|
+
"display_data": {"position": {"x": 0.0, "y": 0.0}},
|
|
1037
|
+
"base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
|
|
1038
|
+
"definition": {
|
|
1039
|
+
"name": "BlankGenericNode",
|
|
1040
|
+
"module": [
|
|
1041
|
+
"vellum_ee",
|
|
1042
|
+
"workflows",
|
|
1043
|
+
"display",
|
|
1044
|
+
"tests",
|
|
1045
|
+
"workflow_serialization",
|
|
1046
|
+
"generic_nodes",
|
|
1047
|
+
"test_ports_serialization",
|
|
1048
|
+
],
|
|
1049
|
+
},
|
|
1050
|
+
"trigger": {"id": "f4cc239d-9feb-4eeb-84d9-62633a7883e7", "merge_behavior": "AWAIT_ATTRIBUTES"},
|
|
1051
|
+
"ports": [
|
|
1052
|
+
{
|
|
1053
|
+
"id": "3ac47591-d4dc-470b-be44-74e1445518e2",
|
|
1054
|
+
"type": "IF",
|
|
1055
|
+
"name": "if_branch",
|
|
1056
|
+
"expression": {
|
|
1057
|
+
"type": "UNARY_EXPRESSION",
|
|
1058
|
+
"lhs": {
|
|
1059
|
+
"type": "WORKFLOW_INPUT",
|
|
1060
|
+
"input_variable_id": str(input_id),
|
|
1061
|
+
},
|
|
1062
|
+
"operator": "blank",
|
|
1063
|
+
},
|
|
1064
|
+
}
|
|
1065
|
+
],
|
|
1066
|
+
"adornments": None,
|
|
1067
|
+
"attributes": [],
|
|
1068
|
+
"outputs": [],
|
|
1069
|
+
},
|
|
1070
|
+
serialized_node,
|
|
1071
|
+
ignore_order=True,
|
|
1072
|
+
)
|
|
1073
|
+
|
|
1074
|
+
|
|
1075
|
+
def test_serialize_node__not_blank(serialize_node):
|
|
1076
|
+
"""
|
|
1077
|
+
Tests that a node with an is_not_blank() port condition serializes correctly.
|
|
1078
|
+
"""
|
|
1079
|
+
|
|
1080
|
+
# GIVEN a node with an is_not_blank() port condition
|
|
1081
|
+
class NotBlankGenericNode(BaseNode):
|
|
1082
|
+
|
|
1083
|
+
class Ports(BaseNode.Ports):
|
|
1084
|
+
if_branch = Port.on_if(Inputs.input.is_not_blank())
|
|
1085
|
+
|
|
1086
|
+
input_id = uuid4()
|
|
1087
|
+
|
|
1088
|
+
# WHEN we serialize the node
|
|
1089
|
+
serialized_node = serialize_node(
|
|
1090
|
+
node_class=NotBlankGenericNode,
|
|
1091
|
+
global_workflow_input_displays={Inputs.input: WorkflowInputsDisplay(id=input_id)},
|
|
1092
|
+
)
|
|
1093
|
+
|
|
1094
|
+
# THEN the serialized node should have the correct structure with a UNARY_EXPRESSION and "notBlank" operator
|
|
1095
|
+
assert not DeepDiff(
|
|
1096
|
+
{
|
|
1097
|
+
"id": "a9349004-bd02-458e-af66-7b515cdd4d3a",
|
|
1098
|
+
"label": "Not Blank Generic Node",
|
|
1099
|
+
"type": "GENERIC",
|
|
1100
|
+
"display_data": {"position": {"x": 0.0, "y": 0.0}},
|
|
1101
|
+
"base": {"name": "BaseNode", "module": ["vellum", "workflows", "nodes", "bases", "base"]},
|
|
1102
|
+
"definition": {
|
|
1103
|
+
"name": "NotBlankGenericNode",
|
|
1104
|
+
"module": [
|
|
1105
|
+
"vellum_ee",
|
|
1106
|
+
"workflows",
|
|
1107
|
+
"display",
|
|
1108
|
+
"tests",
|
|
1109
|
+
"workflow_serialization",
|
|
1110
|
+
"generic_nodes",
|
|
1111
|
+
"test_ports_serialization",
|
|
1112
|
+
],
|
|
1113
|
+
},
|
|
1114
|
+
"trigger": {"id": "60521d64-adc6-4f49-8605-0bf617a23a2d", "merge_behavior": "AWAIT_ATTRIBUTES"},
|
|
1115
|
+
"ports": [
|
|
1116
|
+
{
|
|
1117
|
+
"id": "4824d11b-9d44-4183-8e7f-c4eb21262cc8",
|
|
1118
|
+
"type": "IF",
|
|
1119
|
+
"name": "if_branch",
|
|
1120
|
+
"expression": {
|
|
1121
|
+
"type": "UNARY_EXPRESSION",
|
|
1122
|
+
"lhs": {
|
|
1123
|
+
"type": "WORKFLOW_INPUT",
|
|
1124
|
+
"input_variable_id": str(input_id),
|
|
1125
|
+
},
|
|
1126
|
+
"operator": "notBlank",
|
|
1127
|
+
},
|
|
1128
|
+
}
|
|
1129
|
+
],
|
|
1130
|
+
"adornments": None,
|
|
1131
|
+
"attributes": [],
|
|
1132
|
+
"outputs": [],
|
|
1133
|
+
},
|
|
1134
|
+
serialized_node,
|
|
1135
|
+
ignore_order=True,
|
|
1136
|
+
)
|
|
1137
|
+
|
|
1138
|
+
|
|
1004
1139
|
def test_serialize_node__parse_json(serialize_node):
|
|
1005
1140
|
|
|
1006
1141
|
class ParseJsonGenericNode(BaseNode):
|
|
@@ -1067,3 +1202,54 @@ def test_serialize_node__parse_json(serialize_node):
|
|
|
1067
1202
|
serialized_node,
|
|
1068
1203
|
ignore_order=True,
|
|
1069
1204
|
)
|
|
1205
|
+
|
|
1206
|
+
|
|
1207
|
+
def test_serialize_node__unsupported_descriptor_type():
|
|
1208
|
+
"""
|
|
1209
|
+
Tests that serializing a generic node with an unsupported descriptor type
|
|
1210
|
+
returns the node with an empty expression and adds the error to the display context.
|
|
1211
|
+
"""
|
|
1212
|
+
|
|
1213
|
+
# GIVEN a custom descriptor that is not a supported expression type
|
|
1214
|
+
class UnsupportedDescriptor(BaseDescriptor[bool]):
|
|
1215
|
+
def __init__(self) -> None:
|
|
1216
|
+
super().__init__(name="unsupported", types=(bool,), instance=None)
|
|
1217
|
+
|
|
1218
|
+
# AND a generic node that uses this unsupported descriptor in a port condition
|
|
1219
|
+
class UnsupportedDescriptorNode(BaseNode):
|
|
1220
|
+
class Ports(BaseNode.Ports):
|
|
1221
|
+
if_branch = Port.on_if(UnsupportedDescriptor())
|
|
1222
|
+
|
|
1223
|
+
# AND a display context with dry_run=True to capture errors
|
|
1224
|
+
node_display_class = get_node_display_class(UnsupportedDescriptorNode)
|
|
1225
|
+
node_display = node_display_class()
|
|
1226
|
+
|
|
1227
|
+
context = WorkflowDisplayContext(
|
|
1228
|
+
workflow_display_class=BaseWorkflowDisplay,
|
|
1229
|
+
workflow_display=WorkflowMetaDisplay(
|
|
1230
|
+
entrypoint_node_id=uuid4(),
|
|
1231
|
+
entrypoint_node_source_handle_id=uuid4(),
|
|
1232
|
+
entrypoint_node_display=NodeDisplayData(),
|
|
1233
|
+
),
|
|
1234
|
+
node_displays={UnsupportedDescriptorNode: node_display},
|
|
1235
|
+
dry_run=True,
|
|
1236
|
+
)
|
|
1237
|
+
|
|
1238
|
+
# WHEN we serialize the node
|
|
1239
|
+
serialized_node = node_display.serialize(context)
|
|
1240
|
+
|
|
1241
|
+
# THEN the node should still be returned
|
|
1242
|
+
assert serialized_node["type"] == "GENERIC"
|
|
1243
|
+
|
|
1244
|
+
# AND the port should have a None expression
|
|
1245
|
+
ports = cast(JsonArray, serialized_node["ports"])
|
|
1246
|
+
assert len(ports) == 1
|
|
1247
|
+
port = cast(JsonObject, ports[0])
|
|
1248
|
+
assert port["type"] == "IF"
|
|
1249
|
+
assert port["expression"] is None
|
|
1250
|
+
|
|
1251
|
+
# AND the error should be added to the display context
|
|
1252
|
+
errors = list(context.errors)
|
|
1253
|
+
assert len(errors) == 1
|
|
1254
|
+
assert isinstance(errors[0], UnsupportedSerializationException)
|
|
1255
|
+
assert "Unsupported condition type" in str(errors[0])
|