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
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
1
3
|
from vellum.workflows import BaseWorkflow
|
|
2
4
|
from vellum.workflows.nodes import BaseNode
|
|
3
5
|
from vellum.workflows.nodes.displayable.final_output_node import FinalOutputNode
|
|
4
6
|
from vellum.workflows.state.base import BaseState
|
|
7
|
+
from vellum_ee.workflows.display.utils.exceptions import UnsupportedSerializationException
|
|
5
8
|
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
|
6
9
|
|
|
7
10
|
|
|
@@ -78,3 +81,136 @@ def test_final_output_node_display__serialize_with_invalid_types_should_raise_er
|
|
|
78
81
|
|
|
79
82
|
# AND the serialized workflow should still be created
|
|
80
83
|
assert "workflow_raw_data" in serialized_workflow
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def test_final_output_node_display__serialize_with_list_str_type():
|
|
87
|
+
"""
|
|
88
|
+
Tests that FinalOutputNode with list[str] as second type parameter serializes correctly.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
# GIVEN a node that outputs a list of strings
|
|
92
|
+
class ListNode(BaseNode):
|
|
93
|
+
|
|
94
|
+
class Outputs:
|
|
95
|
+
result: list[str]
|
|
96
|
+
|
|
97
|
+
# AND a FinalOutputNode with list[str] as the second type parameter
|
|
98
|
+
class ListOutput(FinalOutputNode[BaseState, list[str]]):
|
|
99
|
+
class Outputs(FinalOutputNode.Outputs):
|
|
100
|
+
value = ListNode.Outputs.result
|
|
101
|
+
|
|
102
|
+
# AND a workflow referencing the node
|
|
103
|
+
class MyWorkflow(BaseWorkflow):
|
|
104
|
+
graph = ListNode >> ListOutput
|
|
105
|
+
|
|
106
|
+
class Outputs(BaseWorkflow.Outputs):
|
|
107
|
+
final_result = ListOutput.Outputs.value
|
|
108
|
+
|
|
109
|
+
# WHEN we serialize the workflow
|
|
110
|
+
workflow_display = get_workflow_display(workflow_class=MyWorkflow)
|
|
111
|
+
serialized_workflow: dict = workflow_display.serialize()
|
|
112
|
+
|
|
113
|
+
# THEN serialization should succeed without raising validation errors
|
|
114
|
+
assert "workflow_raw_data" in serialized_workflow
|
|
115
|
+
assert "nodes" in serialized_workflow["workflow_raw_data"]
|
|
116
|
+
|
|
117
|
+
# AND the terminal node should be properly serialized
|
|
118
|
+
terminal_node = next(
|
|
119
|
+
node for node in serialized_workflow["workflow_raw_data"]["nodes"] if node["type"] == "TERMINAL"
|
|
120
|
+
)
|
|
121
|
+
assert terminal_node is not None
|
|
122
|
+
assert terminal_node["id"] == str(ListOutput.__id__)
|
|
123
|
+
|
|
124
|
+
# AND the output type should be correctly serialized as JSON
|
|
125
|
+
assert terminal_node["data"]["output_type"] == "JSON"
|
|
126
|
+
|
|
127
|
+
# AND the outputs should contain the correct type information
|
|
128
|
+
assert len(terminal_node["outputs"]) == 1
|
|
129
|
+
assert terminal_node["outputs"][0]["type"] == "JSON"
|
|
130
|
+
|
|
131
|
+
# AND the output should have an inline type reference with JSON Schema
|
|
132
|
+
schema = terminal_node["outputs"][0]["schema"]
|
|
133
|
+
assert schema["type"] == "array"
|
|
134
|
+
assert schema["items"]["type"] == "string"
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def test_final_output_node_display__serialize_with_nested_node_output_reference():
|
|
138
|
+
"""
|
|
139
|
+
Tests that FinalOutputNode with a dict containing nested node output references serializes correctly.
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
# GIVEN a node that outputs multiple values
|
|
143
|
+
class DataNode(BaseNode):
|
|
144
|
+
class Outputs:
|
|
145
|
+
url: str
|
|
146
|
+
count: int
|
|
147
|
+
|
|
148
|
+
# AND a FinalOutputNode with a dict containing nested references to node outputs
|
|
149
|
+
class NestedOutput(FinalOutputNode[BaseState, dict[str, Any]]):
|
|
150
|
+
class Outputs(FinalOutputNode.Outputs):
|
|
151
|
+
value = {
|
|
152
|
+
"download_url": DataNode.Outputs.url,
|
|
153
|
+
"row_count": DataNode.Outputs.count,
|
|
154
|
+
"message": "Data processed successfully",
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
# AND a workflow referencing the node
|
|
158
|
+
class MyWorkflow(BaseWorkflow):
|
|
159
|
+
graph = DataNode >> NestedOutput
|
|
160
|
+
|
|
161
|
+
class Outputs(BaseWorkflow.Outputs):
|
|
162
|
+
final_result = NestedOutput.Outputs.value
|
|
163
|
+
|
|
164
|
+
# WHEN we serialize the workflow
|
|
165
|
+
workflow_display = get_workflow_display(workflow_class=MyWorkflow)
|
|
166
|
+
serialized_workflow: dict = workflow_display.serialize()
|
|
167
|
+
|
|
168
|
+
# THEN serialization should succeed
|
|
169
|
+
assert "workflow_raw_data" in serialized_workflow
|
|
170
|
+
assert "nodes" in serialized_workflow["workflow_raw_data"]
|
|
171
|
+
|
|
172
|
+
# AND the terminal node should be properly serialized
|
|
173
|
+
terminal_node = next(
|
|
174
|
+
node for node in serialized_workflow["workflow_raw_data"]["nodes"] if node["type"] == "TERMINAL"
|
|
175
|
+
)
|
|
176
|
+
assert terminal_node is not None
|
|
177
|
+
assert terminal_node["id"] == str(NestedOutput.__id__)
|
|
178
|
+
|
|
179
|
+
# AND the node should have inputs
|
|
180
|
+
assert len(terminal_node["inputs"]) == 1
|
|
181
|
+
node_input = terminal_node["inputs"][0]
|
|
182
|
+
assert node_input["key"] == "node_input"
|
|
183
|
+
|
|
184
|
+
# AND the input value should have rules with a CONSTANT_VALUE containing the serialized dict
|
|
185
|
+
assert node_input["value"]["combinator"] == "OR"
|
|
186
|
+
assert len(node_input["value"]["rules"]) == 1
|
|
187
|
+
rule = node_input["value"]["rules"][0]
|
|
188
|
+
assert rule["type"] == "CONSTANT_VALUE"
|
|
189
|
+
assert rule["data"]["type"] == "JSON"
|
|
190
|
+
|
|
191
|
+
# AND the serialized value should be a DICTIONARY_REFERENCE with entries
|
|
192
|
+
serialized_value = rule["data"]["value"]
|
|
193
|
+
assert serialized_value["type"] == "DICTIONARY_REFERENCE"
|
|
194
|
+
assert "entries" in serialized_value
|
|
195
|
+
assert len(serialized_value["entries"]) == 3
|
|
196
|
+
|
|
197
|
+
# AND the entries should contain the nested references and constant value
|
|
198
|
+
entry_keys = {entry["key"] for entry in serialized_value["entries"]}
|
|
199
|
+
assert entry_keys == {"download_url", "row_count", "message"}
|
|
200
|
+
|
|
201
|
+
# AND the outputs should contain the DICTIONARY_REFERENCE value
|
|
202
|
+
assert len(terminal_node["outputs"]) == 1
|
|
203
|
+
output = terminal_node["outputs"][0]
|
|
204
|
+
assert output["name"] == "value"
|
|
205
|
+
assert output["type"] == "JSON"
|
|
206
|
+
assert output["value"]["type"] == "DICTIONARY_REFERENCE"
|
|
207
|
+
assert len(output["value"]["entries"]) == 3
|
|
208
|
+
|
|
209
|
+
# AND the attributes should be empty for this node
|
|
210
|
+
assert terminal_node.get("attributes", []) == []
|
|
211
|
+
|
|
212
|
+
# AND a validation error should be recorded for the nested references
|
|
213
|
+
errors = list(workflow_display.display_context.errors)
|
|
214
|
+
assert len(errors) == 1
|
|
215
|
+
assert isinstance(errors[0], UnsupportedSerializationException)
|
|
216
|
+
assert "nested references" in str(errors[0]).lower()
|
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
from vellum.workflows import BaseWorkflow
|
|
2
2
|
from vellum.workflows.nodes.displayable.note_node.node import NoteNode
|
|
3
|
-
from vellum_ee.workflows.display.nodes.vellum.note_node import BaseNoteNodeDisplay
|
|
4
3
|
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
|
5
4
|
|
|
6
5
|
|
|
7
6
|
def test_serialize_node__note_node():
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
"""
|
|
8
|
+
Tests that a single note node is properly serialized in a workflow.
|
|
9
|
+
"""
|
|
11
10
|
|
|
12
|
-
#
|
|
13
|
-
class
|
|
11
|
+
# GIVEN a note node with text and style defined on the node class
|
|
12
|
+
class MyNoteNode(NoteNode):
|
|
14
13
|
text = "This makes sense"
|
|
15
14
|
style = {
|
|
16
15
|
"fontSize": 24,
|
|
17
16
|
}
|
|
18
17
|
|
|
19
|
-
# AND a workflow with the
|
|
18
|
+
# AND a workflow with the note node
|
|
20
19
|
class Workflow(BaseWorkflow):
|
|
21
20
|
graph = MyNoteNode
|
|
22
21
|
|
|
@@ -30,3 +29,41 @@ def test_serialize_node__note_node():
|
|
|
30
29
|
assert my_note_node["inputs"] == []
|
|
31
30
|
assert my_note_node["data"]["text"] == "This makes sense"
|
|
32
31
|
assert my_note_node["data"]["style"] == {"fontSize": 24}
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_serialize_workflow__graph_with_only_note_nodes():
|
|
35
|
+
"""
|
|
36
|
+
Tests that a workflow with only note nodes properly serializes all note nodes in the final payload.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
# GIVEN multiple note nodes with text and style defined on the node classes
|
|
40
|
+
class FirstNoteNode(NoteNode):
|
|
41
|
+
text = "First note"
|
|
42
|
+
style = {"fontSize": 16}
|
|
43
|
+
|
|
44
|
+
class SecondNoteNode(NoteNode):
|
|
45
|
+
text = "Second note"
|
|
46
|
+
style = {"fontSize": 20}
|
|
47
|
+
|
|
48
|
+
# AND a workflow with only note nodes in unused_graphs
|
|
49
|
+
class Workflow(BaseWorkflow):
|
|
50
|
+
unused_graphs = {FirstNoteNode, SecondNoteNode} # type: ignore[assignment]
|
|
51
|
+
|
|
52
|
+
# WHEN the workflow is serialized
|
|
53
|
+
workflow_display = get_workflow_display(workflow_class=Workflow)
|
|
54
|
+
serialized_workflow: dict = workflow_display.serialize()
|
|
55
|
+
|
|
56
|
+
# THEN the serialized workflow should contain both note nodes
|
|
57
|
+
note_nodes = [node for node in serialized_workflow["workflow_raw_data"]["nodes"] if node["type"] == "NOTE"]
|
|
58
|
+
assert len(note_nodes) == 2
|
|
59
|
+
|
|
60
|
+
# AND the note nodes should have the correct data
|
|
61
|
+
note_texts = {node["data"]["text"] for node in note_nodes}
|
|
62
|
+
assert note_texts == {"First note", "Second note"}
|
|
63
|
+
|
|
64
|
+
# AND each note node should have the correct style
|
|
65
|
+
first_note = next(node for node in note_nodes if node["data"]["text"] == "First note")
|
|
66
|
+
second_note = next(node for node in note_nodes if node["data"]["text"] == "Second note")
|
|
67
|
+
|
|
68
|
+
assert first_note["data"]["style"] == {"fontSize": 16}
|
|
69
|
+
assert second_note["data"]["style"] == {"fontSize": 20}
|
|
@@ -154,17 +154,17 @@ def test_serialize_node__prompt_inputs__state_reference():
|
|
|
154
154
|
workflow_display = get_workflow_display(workflow_class=Workflow)
|
|
155
155
|
serialized_workflow: dict = workflow_display.serialize()
|
|
156
156
|
|
|
157
|
-
# THEN the node should skip the state reference input rule
|
|
158
157
|
my_prompt_node = next(
|
|
159
158
|
node for node in serialized_workflow["workflow_raw_data"]["nodes"] if node["id"] == str(MyPromptNode.__id__)
|
|
160
159
|
)
|
|
161
|
-
|
|
162
160
|
assert my_prompt_node["inputs"] == [
|
|
163
161
|
{
|
|
164
162
|
"id": "7c5d23b3-c5ed-4ed6-a685-43fbe9a9baf8",
|
|
165
163
|
"key": "foo",
|
|
166
164
|
"value": {
|
|
167
|
-
"rules": [
|
|
165
|
+
"rules": [
|
|
166
|
+
{"type": "WORKFLOW_STATE", "data": {"state_variable_id": "dd3391bf-c818-4eba-aac5-912618ba412f"}}
|
|
167
|
+
],
|
|
168
168
|
"combinator": "OR",
|
|
169
169
|
},
|
|
170
170
|
},
|
|
@@ -172,15 +172,7 @@ def test_serialize_node__prompt_inputs__state_reference():
|
|
|
172
172
|
"id": "e138f06e-d705-46bc-8ac4-c844b0e9131a",
|
|
173
173
|
"key": "bar",
|
|
174
174
|
"value": {
|
|
175
|
-
"rules": [
|
|
176
|
-
{
|
|
177
|
-
"type": "CONSTANT_VALUE",
|
|
178
|
-
"data": {
|
|
179
|
-
"type": "STRING",
|
|
180
|
-
"value": "baz",
|
|
181
|
-
},
|
|
182
|
-
}
|
|
183
|
-
],
|
|
175
|
+
"rules": [{"type": "CONSTANT_VALUE", "data": {"type": "STRING", "value": "baz"}}],
|
|
184
176
|
"combinator": "OR",
|
|
185
177
|
},
|
|
186
178
|
},
|
|
@@ -201,7 +193,7 @@ def test_serialize_node__prompt_inputs__state_reference():
|
|
|
201
193
|
"key": "foo",
|
|
202
194
|
"value": {
|
|
203
195
|
"type": "WORKFLOW_STATE",
|
|
204
|
-
"state_variable_id": "
|
|
196
|
+
"state_variable_id": "dd3391bf-c818-4eba-aac5-912618ba412f",
|
|
205
197
|
},
|
|
206
198
|
},
|
|
207
199
|
{
|
|
@@ -3,6 +3,12 @@ from datetime import datetime
|
|
|
3
3
|
from uuid import UUID, uuid4
|
|
4
4
|
from typing import Type
|
|
5
5
|
|
|
6
|
+
from vellum import (
|
|
7
|
+
ReleaseEnvironment,
|
|
8
|
+
WorkflowDeploymentRelease,
|
|
9
|
+
WorkflowDeploymentReleaseWorkflowDeployment,
|
|
10
|
+
WorkflowDeploymentReleaseWorkflowVersion,
|
|
11
|
+
)
|
|
6
12
|
from vellum.workflows import BaseWorkflow
|
|
7
13
|
from vellum.workflows.nodes.displayable.subworkflow_deployment_node.node import SubworkflowDeploymentNode
|
|
8
14
|
from vellum_ee.workflows.display.nodes.vellum.subworkflow_deployment_node import BaseSubworkflowDeploymentNodeDisplay
|
|
@@ -29,28 +35,32 @@ def _display_class_with_node_input_ids_by_name_with_inputs_prefix(Node: Type[Sub
|
|
|
29
35
|
|
|
30
36
|
@pytest.fixture
|
|
31
37
|
def mock_fetch_deployment(mocker):
|
|
32
|
-
# Create a mock deployment response
|
|
33
|
-
|
|
34
|
-
id=
|
|
35
|
-
name="test-deployment",
|
|
36
|
-
label="Test Deployment",
|
|
37
|
-
status="ACTIVE",
|
|
38
|
-
environment="DEVELOPMENT",
|
|
38
|
+
# Create a mock deployment release response
|
|
39
|
+
deployment_release = WorkflowDeploymentRelease(
|
|
40
|
+
id=str(uuid4()),
|
|
39
41
|
created=datetime.now(),
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
environment=ReleaseEnvironment(id=str(uuid4()), name="DEVELOPMENT", label="Development"),
|
|
43
|
+
workflow_version=WorkflowDeploymentReleaseWorkflowVersion(
|
|
44
|
+
id=str(uuid4()),
|
|
45
|
+
input_variables=[],
|
|
46
|
+
output_variables=[],
|
|
47
|
+
),
|
|
48
|
+
deployment=WorkflowDeploymentReleaseWorkflowDeployment(
|
|
49
|
+
id="test-id",
|
|
50
|
+
name="test-deployment",
|
|
51
|
+
),
|
|
52
|
+
release_tags=[],
|
|
53
|
+
reviews=[],
|
|
45
54
|
)
|
|
46
55
|
|
|
47
|
-
# Patch the
|
|
48
|
-
|
|
49
|
-
"vellum.client.resources.workflow_deployments.client.
|
|
50
|
-
|
|
56
|
+
# Patch the retrieve_workflow_deployment_release method
|
|
57
|
+
patch_path = (
|
|
58
|
+
"vellum.client.resources.workflow_deployments.client."
|
|
59
|
+
"WorkflowDeploymentsClient.retrieve_workflow_deployment_release"
|
|
51
60
|
)
|
|
61
|
+
mocker.patch(patch_path, return_value=deployment_release)
|
|
52
62
|
|
|
53
|
-
return
|
|
63
|
+
return deployment_release
|
|
54
64
|
|
|
55
65
|
|
|
56
66
|
@pytest.mark.parametrize(
|
|
@@ -153,7 +153,9 @@ def test_serialize_node__prompt_inputs__mixed_values():
|
|
|
153
153
|
|
|
154
154
|
|
|
155
155
|
def test_serialize_node__tool_calling_node__mcp_server_api_key():
|
|
156
|
-
|
|
156
|
+
"""Tests that MCPServer with EnvironmentVariableReference serializes as ARRAY_REFERENCE."""
|
|
157
|
+
|
|
158
|
+
# GIVEN a tool calling node with an mcp server using an environment variable for the API key
|
|
157
159
|
class MyToolCallingNode(ToolCallingNode):
|
|
158
160
|
functions = [
|
|
159
161
|
MCPServer(
|
|
@@ -184,26 +186,70 @@ def test_serialize_node__tool_calling_node__mcp_server_api_key():
|
|
|
184
186
|
attribute for attribute in my_tool_calling_node["attributes"] if attribute["name"] == "functions"
|
|
185
187
|
)
|
|
186
188
|
|
|
189
|
+
# AND the functions attribute should be an ARRAY_REFERENCE with a DICTIONARY_REFERENCE
|
|
190
|
+
# containing the MCP server fields, with api_key_header_value as ENVIRONMENT_VARIABLE
|
|
187
191
|
assert functions_attribute == {
|
|
188
192
|
"id": "ff00c2d6-f99c-458b-9bcd-181f8e43b2d1",
|
|
189
193
|
"name": "functions",
|
|
190
194
|
"value": {
|
|
191
|
-
"type": "
|
|
192
|
-
"
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
195
|
+
"type": "ARRAY_REFERENCE",
|
|
196
|
+
"items": [
|
|
197
|
+
{
|
|
198
|
+
"type": "DICTIONARY_REFERENCE",
|
|
199
|
+
"entries": [
|
|
200
|
+
{
|
|
201
|
+
"id": "8cff4f0a-86d9-43fd-8d0b-542c845db53e",
|
|
202
|
+
"key": "type",
|
|
203
|
+
"value": {"type": "CONSTANT_VALUE", "value": {"type": "STRING", "value": "MCP_SERVER"}},
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"id": "29203be4-407c-4056-aaa3-6e6d1249113e",
|
|
207
|
+
"key": "name",
|
|
208
|
+
"value": {"type": "CONSTANT_VALUE", "value": {"type": "STRING", "value": "my-mcp-server"}},
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
"id": "69813bb2-12c1-432b-9ef3-a0071bd29149",
|
|
212
|
+
"key": "description",
|
|
213
|
+
"value": {"type": "CONSTANT_VALUE", "value": {"type": "STRING", "value": ""}},
|
|
214
|
+
},
|
|
215
|
+
{
|
|
216
|
+
"id": "83cd2f84-bf35-4996-9840-3754a79e1091",
|
|
217
|
+
"key": "url",
|
|
218
|
+
"value": {
|
|
219
|
+
"type": "CONSTANT_VALUE",
|
|
220
|
+
"value": {"type": "STRING", "value": "https://my-mcp-server.com"},
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
"id": "5ad23cee-497e-4ca3-ba51-d13f56985c75",
|
|
225
|
+
"key": "authorization_type",
|
|
226
|
+
"value": {"type": "CONSTANT_VALUE", "value": {"type": "STRING", "value": "API_KEY"}},
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
"id": "45964d28-1a9b-40a1-b544-62da92d2f62a",
|
|
230
|
+
"key": "bearer_token_value",
|
|
231
|
+
"value": {"type": "CONSTANT_VALUE", "value": {"type": "JSON", "value": None}},
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
"id": "c4952fa6-1ffb-4e88-863f-3d0867b19b7a",
|
|
235
|
+
"key": "api_key_header_key",
|
|
236
|
+
"value": {
|
|
237
|
+
"type": "CONSTANT_VALUE",
|
|
238
|
+
"value": {"type": "STRING", "value": "my-api-key-header-key"},
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
"id": "7dc9cdb0-d139-4a1d-8c6f-9941c6b82b62",
|
|
243
|
+
"key": "api_key_header_value",
|
|
244
|
+
"value": {
|
|
245
|
+
"type": "ENVIRONMENT_VARIABLE",
|
|
246
|
+
"environment_variable": "my-api-key-header-value",
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
],
|
|
250
|
+
"definition": {"name": "MCPServer", "module": ["vellum", "workflows", "types", "definition"]},
|
|
251
|
+
}
|
|
252
|
+
],
|
|
207
253
|
},
|
|
208
254
|
}
|
|
209
255
|
|
|
@@ -328,7 +374,7 @@ def test_serialize_tool_router_node():
|
|
|
328
374
|
"lhs": {
|
|
329
375
|
"lhs": {
|
|
330
376
|
"lhs": {
|
|
331
|
-
"state_variable_id": "
|
|
377
|
+
"state_variable_id": "30a4672a-96dc-471a-878c-90e0f1f7f043",
|
|
332
378
|
"type": "WORKFLOW_STATE",
|
|
333
379
|
},
|
|
334
380
|
"operator": "<",
|
|
@@ -354,7 +400,7 @@ def test_serialize_tool_router_node():
|
|
|
354
400
|
},
|
|
355
401
|
"operator": "accessField",
|
|
356
402
|
"rhs": {
|
|
357
|
-
"state_variable_id": "
|
|
403
|
+
"state_variable_id": "30a4672a-96dc-471a-878c-90e0f1f7f043",
|
|
358
404
|
"type": "WORKFLOW_STATE",
|
|
359
405
|
},
|
|
360
406
|
"type": "BINARY_EXPRESSION",
|
|
@@ -381,7 +427,7 @@ def test_serialize_tool_router_node():
|
|
|
381
427
|
},
|
|
382
428
|
"operator": "accessField",
|
|
383
429
|
"rhs": {
|
|
384
|
-
"state_variable_id": "
|
|
430
|
+
"state_variable_id": "30a4672a-96dc-471a-878c-90e0f1f7f043",
|
|
385
431
|
"type": "WORKFLOW_STATE",
|
|
386
432
|
},
|
|
387
433
|
"type": "BINARY_EXPRESSION",
|
|
@@ -453,6 +499,83 @@ def test_serialize_function_node():
|
|
|
453
499
|
assert display_data["color"] == "purple"
|
|
454
500
|
|
|
455
501
|
|
|
502
|
+
def test_serialize_inline_prompt_node__mcp_server_not_serialized():
|
|
503
|
+
"""
|
|
504
|
+
Test that MCP servers in inline prompt node functions are not serialized as function blocks.
|
|
505
|
+
MCP servers should be skipped during serialization (they return None from _generate_function_tools).
|
|
506
|
+
"""
|
|
507
|
+
|
|
508
|
+
# GIVEN an MCP server
|
|
509
|
+
mcp_server = MCPServer(
|
|
510
|
+
name="my-mcp-server",
|
|
511
|
+
url="https://my-mcp-server.com",
|
|
512
|
+
authorization_type=AuthorizationType.API_KEY,
|
|
513
|
+
api_key_header_key="my-api-key-header-key",
|
|
514
|
+
api_key_header_value=EnvironmentVariableReference(name="my-api-key-header-value"),
|
|
515
|
+
)
|
|
516
|
+
|
|
517
|
+
# AND a regular function
|
|
518
|
+
def my_function(arg1: str) -> str:
|
|
519
|
+
return f"Result: {arg1}"
|
|
520
|
+
|
|
521
|
+
# AND an inline prompt node with both MCP server and regular function
|
|
522
|
+
class MyInlinePromptNode(InlinePromptNode):
|
|
523
|
+
ml_model = "gpt-4o-mini"
|
|
524
|
+
blocks = []
|
|
525
|
+
functions = [mcp_server, my_function]
|
|
526
|
+
prompt_inputs = None
|
|
527
|
+
parameters = PromptParameters()
|
|
528
|
+
|
|
529
|
+
# WHEN we serialize the inline prompt node
|
|
530
|
+
inline_prompt_node_display_class = get_node_display_class(MyInlinePromptNode)
|
|
531
|
+
inline_prompt_node_display = inline_prompt_node_display_class()
|
|
532
|
+
|
|
533
|
+
class Workflow(BaseWorkflow[BaseInputs, BaseState]):
|
|
534
|
+
graph = MyInlinePromptNode
|
|
535
|
+
|
|
536
|
+
workflow_display = get_workflow_display(workflow_class=Workflow)
|
|
537
|
+
display_context = workflow_display.display_context
|
|
538
|
+
|
|
539
|
+
serialized_node = inline_prompt_node_display.serialize(display_context)
|
|
540
|
+
|
|
541
|
+
# THEN the serialized node should have exec_config with prompt_template_block_data
|
|
542
|
+
assert isinstance(serialized_node, dict)
|
|
543
|
+
assert serialized_node["type"] == "PROMPT"
|
|
544
|
+
assert isinstance(serialized_node["data"], dict)
|
|
545
|
+
assert "exec_config" in serialized_node["data"]
|
|
546
|
+
exec_config = serialized_node["data"]["exec_config"]
|
|
547
|
+
assert isinstance(exec_config, dict)
|
|
548
|
+
assert "prompt_template_block_data" in exec_config
|
|
549
|
+
prompt_template_block_data = exec_config["prompt_template_block_data"]
|
|
550
|
+
assert isinstance(prompt_template_block_data, dict)
|
|
551
|
+
blocks = prompt_template_block_data["blocks"]
|
|
552
|
+
assert isinstance(blocks, list)
|
|
553
|
+
|
|
554
|
+
# AND there should be only one FUNCTION_DEFINITION block (from the regular function)
|
|
555
|
+
# MCP server should not be serialized
|
|
556
|
+
function_blocks = [
|
|
557
|
+
block for block in blocks if isinstance(block, dict) and block.get("block_type") == "FUNCTION_DEFINITION"
|
|
558
|
+
]
|
|
559
|
+
assert len(function_blocks) == 1
|
|
560
|
+
assert function_blocks == [
|
|
561
|
+
{
|
|
562
|
+
"id": "b6b7b0c2-78b6-498f-8f97-fdaa81e082ec",
|
|
563
|
+
"block_type": "FUNCTION_DEFINITION",
|
|
564
|
+
"properties": {
|
|
565
|
+
"function_name": "my_function",
|
|
566
|
+
"function_description": None,
|
|
567
|
+
"function_parameters": {
|
|
568
|
+
"type": "object",
|
|
569
|
+
"properties": {"arg1": {"type": "string"}},
|
|
570
|
+
"required": ["arg1"],
|
|
571
|
+
},
|
|
572
|
+
"function_forced": None,
|
|
573
|
+
"function_strict": None,
|
|
574
|
+
},
|
|
575
|
+
}
|
|
576
|
+
]
|
|
577
|
+
|
|
578
|
+
|
|
456
579
|
def test_serialize_node__tool_calling_node__subworkflow_with_parent_input_reference():
|
|
457
580
|
"""
|
|
458
581
|
Test that a tool calling node with a subworkflow that references parent inputs serializes correctly
|
|
@@ -594,7 +717,7 @@ def test_serialize_tool_prompt_node_with_inline_workflow():
|
|
|
594
717
|
"operator": "concat",
|
|
595
718
|
"rhs": {
|
|
596
719
|
"type": "WORKFLOW_STATE",
|
|
597
|
-
"state_variable_id": "
|
|
720
|
+
"state_variable_id": "c1d692a7-3d87-4283-8d9c-daee82c61854",
|
|
598
721
|
},
|
|
599
722
|
},
|
|
600
723
|
}
|
|
@@ -621,7 +744,7 @@ def test_serialize_tool_prompt_node_with_workflow_deployment(vellum_client):
|
|
|
621
744
|
input_variables=[],
|
|
622
745
|
output_variables=[],
|
|
623
746
|
),
|
|
624
|
-
deployment=WorkflowDeploymentReleaseWorkflowDeployment(name="test-name"),
|
|
747
|
+
deployment=WorkflowDeploymentReleaseWorkflowDeployment(id="test-deployment-id", name="test-name"),
|
|
625
748
|
description="test-description",
|
|
626
749
|
release_tags=[
|
|
627
750
|
ReleaseReleaseTag(
|