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
|
@@ -19,6 +19,7 @@ from typing import (
|
|
|
19
19
|
get_origin,
|
|
20
20
|
)
|
|
21
21
|
|
|
22
|
+
from vellum.client import Vellum as VellumClient
|
|
22
23
|
from vellum.client.types.code_resource_definition import CodeResourceDefinition
|
|
23
24
|
from vellum.workflows import BaseWorkflow
|
|
24
25
|
from vellum.workflows.constants import undefined
|
|
@@ -30,12 +31,14 @@ from vellum.workflows.references.node import NodeReference
|
|
|
30
31
|
from vellum.workflows.types.core import JsonArray, JsonObject
|
|
31
32
|
from vellum.workflows.types.generics import NodeType
|
|
32
33
|
from vellum.workflows.types.utils import get_original_base
|
|
34
|
+
from vellum.workflows.utils.functions import compile_annotation
|
|
33
35
|
from vellum.workflows.utils.names import pascal_to_title_case
|
|
34
36
|
from vellum.workflows.utils.uuids import uuid4_from_hash
|
|
35
37
|
from vellum.workflows.utils.vellum_variables import primitive_type_to_vellum_variable_type
|
|
36
|
-
from vellum_ee.workflows.display.editor.types import NodeDisplayComment, NodeDisplayData
|
|
38
|
+
from vellum_ee.workflows.display.editor.types import NodeDisplayComment, NodeDisplayData, NodeDisplayPosition
|
|
37
39
|
from vellum_ee.workflows.display.nodes.get_node_display_class import get_node_display_class
|
|
38
40
|
from vellum_ee.workflows.display.nodes.types import NodeOutputDisplay, PortDisplay, PortDisplayOverrides
|
|
41
|
+
from vellum_ee.workflows.display.utils.exceptions import NodeValidationError, UnsupportedSerializationException
|
|
39
42
|
from vellum_ee.workflows.display.utils.expressions import serialize_value
|
|
40
43
|
from vellum_ee.workflows.display.utils.registry import register_node_display_class
|
|
41
44
|
|
|
@@ -60,10 +63,9 @@ class BaseNodeDisplayMeta(type):
|
|
|
60
63
|
cls = cast(Type["BaseNodeDisplay"], super().__new__(mcs, name, bases, dct))
|
|
61
64
|
# This cast shouldn't be necessary, but it's a workaround for a mypy bug
|
|
62
65
|
node_class = cast(Type[BaseNode], cls.infer_node_class() if name != "BaseNodeDisplay" else BaseNode)
|
|
63
|
-
|
|
64
66
|
if not dct.get("output_display"):
|
|
65
67
|
cls.output_display = {
|
|
66
|
-
ref: NodeOutputDisplay(id=node_class.__output_ids__[ref.name], name=ref.name)
|
|
68
|
+
ref: NodeOutputDisplay(id=node_class.__output_ids__[ref.name], name=ref.name, _is_implicit=True)
|
|
67
69
|
for ref in node_class.Outputs
|
|
68
70
|
if ref.name in node_class.__output_ids__
|
|
69
71
|
}
|
|
@@ -140,6 +142,11 @@ class BaseNodeDisplay(Generic[NodeType], metaclass=BaseNodeDisplayMeta):
|
|
|
140
142
|
__unserializable_attributes__: Set[NodeReference] = set()
|
|
141
143
|
# END: Attributes for backwards compatible serialization
|
|
142
144
|
|
|
145
|
+
def build(self, client: VellumClient) -> None:
|
|
146
|
+
# Individual display classes can override this method to perform any async logic
|
|
147
|
+
# needed to perform serialization across all nodes.
|
|
148
|
+
pass
|
|
149
|
+
|
|
143
150
|
def serialize(self, display_context: "WorkflowDisplayContext", **kwargs: Any) -> JsonObject:
|
|
144
151
|
node = self._node
|
|
145
152
|
node_id = self.node_id
|
|
@@ -202,14 +209,18 @@ class BaseNodeDisplay(Generic[NodeType], metaclass=BaseNodeDisplayMeta):
|
|
|
202
209
|
for port in node.Ports:
|
|
203
210
|
id = str(self.get_node_port_display(port).id)
|
|
204
211
|
if port._condition_type:
|
|
212
|
+
expression = None
|
|
213
|
+
if port._condition:
|
|
214
|
+
try:
|
|
215
|
+
expression = serialize_value(node_id, display_context, port._condition)
|
|
216
|
+
except UnsupportedSerializationException as e:
|
|
217
|
+
display_context.add_error(e)
|
|
205
218
|
ports.append(
|
|
206
219
|
{
|
|
207
220
|
"id": id,
|
|
208
221
|
"name": port.name,
|
|
209
222
|
"type": port._condition_type.value,
|
|
210
|
-
"expression":
|
|
211
|
-
serialize_value(node_id, display_context, port._condition) if port._condition else None
|
|
212
|
-
),
|
|
223
|
+
"expression": expression,
|
|
213
224
|
}
|
|
214
225
|
)
|
|
215
226
|
else:
|
|
@@ -275,6 +286,16 @@ class BaseNodeDisplay(Generic[NodeType], metaclass=BaseNodeDisplayMeta):
|
|
|
275
286
|
if output in self.output_display
|
|
276
287
|
else str(uuid4_from_hash(f"{self.node_id}|{output.name}"))
|
|
277
288
|
)
|
|
289
|
+
try:
|
|
290
|
+
schema = compile_annotation(output.normalized_type, {})
|
|
291
|
+
except Exception as e:
|
|
292
|
+
display_context.add_error(
|
|
293
|
+
NodeValidationError(
|
|
294
|
+
message=f"Failed to compile output schema for output '{output.name}': {e}",
|
|
295
|
+
node_class_name=self._node.__name__,
|
|
296
|
+
)
|
|
297
|
+
)
|
|
298
|
+
schema = None
|
|
278
299
|
|
|
279
300
|
outputs.append(
|
|
280
301
|
{
|
|
@@ -282,6 +303,7 @@ class BaseNodeDisplay(Generic[NodeType], metaclass=BaseNodeDisplayMeta):
|
|
|
282
303
|
"name": output.name,
|
|
283
304
|
"type": output_type,
|
|
284
305
|
"value": value,
|
|
306
|
+
"schema": schema,
|
|
285
307
|
}
|
|
286
308
|
)
|
|
287
309
|
|
|
@@ -480,6 +502,17 @@ class BaseNodeDisplay(Generic[NodeType], metaclass=BaseNodeDisplayMeta):
|
|
|
480
502
|
if self._node.Display.color is not None and self._node.Display.color != base_node.Display.color:
|
|
481
503
|
base_kwargs["color"] = self._node.Display.color
|
|
482
504
|
|
|
505
|
+
# Add position from x, y if they exist
|
|
506
|
+
if self._node.Display.x is not None or self._node.Display.y is not None:
|
|
507
|
+
base_kwargs["position"] = NodeDisplayPosition(
|
|
508
|
+
x=self._node.Display.x if self._node.Display.x is not None else 0.0,
|
|
509
|
+
y=self._node.Display.y if self._node.Display.y is not None else 0.0,
|
|
510
|
+
)
|
|
511
|
+
|
|
512
|
+
# Add z_index if it exists
|
|
513
|
+
if self._node.Display.z_index is not None and self._node.Display.z_index != base_node.Display.z_index:
|
|
514
|
+
base_kwargs["z_index"] = self._node.Display.z_index
|
|
515
|
+
|
|
483
516
|
# Add docstring as comment if present
|
|
484
517
|
if docstring:
|
|
485
518
|
base_kwargs["comment"] = NodeDisplayComment(value=docstring, expanded=True)
|
|
@@ -492,16 +525,16 @@ class BaseNodeDisplay(Generic[NodeType], metaclass=BaseNodeDisplayMeta):
|
|
|
492
525
|
# Get fields that were explicitly set for z_index handling
|
|
493
526
|
fields_set = explicit_value.model_fields_set
|
|
494
527
|
|
|
528
|
+
# Override position only if explicitly set (since it has a default value)
|
|
529
|
+
if "position" in fields_set:
|
|
530
|
+
base_kwargs["position"] = explicit_value.position
|
|
531
|
+
|
|
495
532
|
# Override simple attributes (only if not None)
|
|
496
|
-
for attr in ("
|
|
533
|
+
for attr in ("width", "height", "icon", "color", "z_index"):
|
|
497
534
|
value = getattr(explicit_value, attr, None)
|
|
498
535
|
if value is not None:
|
|
499
536
|
base_kwargs[attr] = value
|
|
500
537
|
|
|
501
|
-
# Include z_index if explicitly set (even if None)
|
|
502
|
-
if "z_index" in fields_set:
|
|
503
|
-
base_kwargs["z_index"] = explicit_value.z_index
|
|
504
|
-
|
|
505
538
|
# Special handling for comment: merge docstring with explicit comment's expanded state
|
|
506
539
|
if explicit_value.comment:
|
|
507
540
|
base_kwargs["comment"] = (
|
|
@@ -246,3 +246,96 @@ def test_serialize_display_class_used_as_fallback():
|
|
|
246
246
|
assert display_data["icon"] == "vellum:icon:star" # Falls back to Display class
|
|
247
247
|
assert display_data["color"] == "green" # Falls back to Display class
|
|
248
248
|
assert display_data["position"] == {"x": 50, "y": 75} # From BaseNodeDisplay
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def test_serialize_basenode_display_with_xyz():
|
|
252
|
+
"""Tests that BaseNode.Display x, y, z_index attributes serialize correctly."""
|
|
253
|
+
|
|
254
|
+
# GIVEN a node with x, y, z_index in Display class
|
|
255
|
+
class MyNode(BaseNode):
|
|
256
|
+
class Display:
|
|
257
|
+
x = 100.0
|
|
258
|
+
y = 200.0
|
|
259
|
+
z_index = 5
|
|
260
|
+
|
|
261
|
+
# WHEN we serialize the node
|
|
262
|
+
node_display_class = get_node_display_class(MyNode)
|
|
263
|
+
data = node_display_class().serialize(WorkflowDisplayContext())
|
|
264
|
+
|
|
265
|
+
# THEN the display_data should include position and z_index from Display class
|
|
266
|
+
display_data = data["display_data"]
|
|
267
|
+
assert isinstance(display_data, dict)
|
|
268
|
+
assert display_data["position"] == {"x": 100.0, "y": 200.0}
|
|
269
|
+
assert display_data["z_index"] == 5
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
def test_serialize_basenode_display_with_partial_xy():
|
|
273
|
+
"""Tests that BaseNode.Display with only x or y still creates position."""
|
|
274
|
+
|
|
275
|
+
# GIVEN a node with only x in Display class
|
|
276
|
+
class MyNodeX(BaseNode):
|
|
277
|
+
class Display:
|
|
278
|
+
x = 150.0
|
|
279
|
+
|
|
280
|
+
# WHEN we serialize the node
|
|
281
|
+
node_display_class = get_node_display_class(MyNodeX)
|
|
282
|
+
data = node_display_class().serialize(WorkflowDisplayContext())
|
|
283
|
+
|
|
284
|
+
# THEN the display_data should include position with x and default y
|
|
285
|
+
display_data = data["display_data"]
|
|
286
|
+
assert isinstance(display_data, dict)
|
|
287
|
+
assert display_data["position"] == {"x": 150.0, "y": 0.0}
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
def test_serialize_explicit_display_data_overrides_display_class_xyz():
|
|
291
|
+
"""Tests that BaseNodeDisplay's explicit display_data takes precedence over Display class x, y, z_index."""
|
|
292
|
+
|
|
293
|
+
# GIVEN a node with x, y, z_index in Display class
|
|
294
|
+
class MyNode(BaseNode):
|
|
295
|
+
class Display:
|
|
296
|
+
x = 100.0
|
|
297
|
+
y = 200.0
|
|
298
|
+
z_index = 5
|
|
299
|
+
|
|
300
|
+
# AND a BaseNodeDisplay with explicit display_data
|
|
301
|
+
class MyNodeDisplay(BaseNodeDisplay[MyNode]):
|
|
302
|
+
display_data = NodeDisplayData(
|
|
303
|
+
position=NodeDisplayPosition(x=300, y=400),
|
|
304
|
+
z_index=10,
|
|
305
|
+
)
|
|
306
|
+
|
|
307
|
+
# WHEN we serialize the node
|
|
308
|
+
data = MyNodeDisplay().serialize(WorkflowDisplayContext())
|
|
309
|
+
|
|
310
|
+
# THEN the display_data should use values from BaseNodeDisplay
|
|
311
|
+
display_data = data["display_data"]
|
|
312
|
+
assert isinstance(display_data, dict)
|
|
313
|
+
assert display_data["position"] == {"x": 300, "y": 400} # BaseNodeDisplay overrides
|
|
314
|
+
assert display_data["z_index"] == 10 # BaseNodeDisplay overrides
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def test_serialize_display_class_xyz_used_as_fallback():
|
|
318
|
+
"""Tests that Display class x, y, z_index are used when BaseNodeDisplay doesn't specify them."""
|
|
319
|
+
|
|
320
|
+
# GIVEN a node with x, y, z_index in Display class
|
|
321
|
+
class MyNode(BaseNode):
|
|
322
|
+
class Display:
|
|
323
|
+
x = 50.0
|
|
324
|
+
y = 75.0
|
|
325
|
+
z_index = 3
|
|
326
|
+
|
|
327
|
+
# AND a BaseNodeDisplay with only icon specified
|
|
328
|
+
class MyNodeDisplay(BaseNodeDisplay[MyNode]):
|
|
329
|
+
display_data = NodeDisplayData(
|
|
330
|
+
icon="vellum:icon:star",
|
|
331
|
+
)
|
|
332
|
+
|
|
333
|
+
# WHEN we serialize the node
|
|
334
|
+
data = MyNodeDisplay().serialize(WorkflowDisplayContext())
|
|
335
|
+
|
|
336
|
+
# THEN the display_data should use x, y, z from Display class as fallback
|
|
337
|
+
display_data = data["display_data"]
|
|
338
|
+
assert isinstance(display_data, dict)
|
|
339
|
+
assert display_data["position"] == {"x": 50.0, "y": 75.0} # Falls back to Display class
|
|
340
|
+
assert display_data["z_index"] == 3 # Falls back to Display class
|
|
341
|
+
assert display_data["icon"] == "vellum:icon:star" # From BaseNodeDisplay
|
|
@@ -4,7 +4,6 @@ from .code_execution_node import BaseCodeExecutionNodeDisplay
|
|
|
4
4
|
from .conditional_node import BaseConditionalNodeDisplay
|
|
5
5
|
from .error_node import BaseErrorNodeDisplay
|
|
6
6
|
from .final_output_node import BaseFinalOutputNodeDisplay
|
|
7
|
-
from .function_node import FunctionNodeDisplay
|
|
8
7
|
from .guardrail_node import BaseGuardrailNodeDisplay
|
|
9
8
|
from .inline_prompt_node import BaseInlinePromptNodeDisplay
|
|
10
9
|
from .inline_subworkflow_node import BaseInlineSubworkflowNodeDisplay
|
|
@@ -26,7 +25,6 @@ __all__ = [
|
|
|
26
25
|
"BaseConditionalNodeDisplay",
|
|
27
26
|
"BaseErrorNodeDisplay",
|
|
28
27
|
"BaseFinalOutputNodeDisplay",
|
|
29
|
-
"FunctionNodeDisplay",
|
|
30
28
|
"BaseGuardrailNodeDisplay",
|
|
31
29
|
"BaseInlinePromptNodeDisplay",
|
|
32
30
|
"BaseInlineSubworkflowNodeDisplay",
|
|
@@ -89,8 +89,11 @@ class BaseAdornmentNodeDisplay(BaseNodeDisplay[_BaseAdornmentNodeType], Generic[
|
|
|
89
89
|
"Unable to serialize standalone adornment nodes. Please use adornment nodes as a decorator."
|
|
90
90
|
)
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
wrapped_node_display =
|
|
92
|
+
# Use existing node display instance from display_context if available to preserve build() data
|
|
93
|
+
wrapped_node_display = display_context.node_displays.get(wrapped_node)
|
|
94
|
+
if not wrapped_node_display:
|
|
95
|
+
wrapped_node_display_class = get_node_display_class(wrapped_node)
|
|
96
|
+
wrapped_node_display = wrapped_node_display_class()
|
|
94
97
|
additional_kwargs = get_additional_kwargs(wrapped_node_display.node_id) if get_additional_kwargs else {}
|
|
95
98
|
serialized_wrapped_node = wrapped_node_display.serialize(display_context, **kwargs, **additional_kwargs)
|
|
96
99
|
|
|
@@ -119,5 +119,5 @@ class BaseCodeExecutionNodeDisplay(BaseNodeDisplay[_CodeExecutionNodeType], Gene
|
|
|
119
119
|
"output_id": str(self.output_id) if self.output_id else str(output_display.id),
|
|
120
120
|
"log_output_id": str(self.log_output_id) if self.log_output_id else str(log_output_display.id),
|
|
121
121
|
},
|
|
122
|
-
**self.serialize_generic_fields(display_context
|
|
122
|
+
**self.serialize_generic_fields(display_context),
|
|
123
123
|
}
|
|
@@ -2,10 +2,11 @@ from uuid import UUID
|
|
|
2
2
|
from typing import TYPE_CHECKING, Callable, Dict, Generic, List, Optional, Tuple, Type, TypeVar, Union
|
|
3
3
|
|
|
4
4
|
from vellum import FunctionDefinition, PromptBlock, RichTextChildBlock, VellumVariable
|
|
5
|
+
from vellum.workflows import MCPServer
|
|
5
6
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
|
6
7
|
from vellum.workflows.nodes import InlinePromptNode
|
|
7
8
|
from vellum.workflows.types.core import JsonObject
|
|
8
|
-
from vellum.workflows.types.definition import DeploymentDefinition, VellumIntegrationToolDefinition
|
|
9
|
+
from vellum.workflows.types.definition import DeploymentDefinition, MCPToolDefinition, VellumIntegrationToolDefinition
|
|
9
10
|
from vellum.workflows.types.generics import is_workflow_class
|
|
10
11
|
from vellum.workflows.utils.functions import (
|
|
11
12
|
compile_function_definition,
|
|
@@ -82,6 +83,7 @@ class BaseInlinePromptNodeDisplay(BaseNodeDisplay[_InlinePromptNodeType], Generi
|
|
|
82
83
|
[
|
|
83
84
|
self._generate_function_tools(function, i, display_context)
|
|
84
85
|
for i, function in enumerate(function_definitions)
|
|
86
|
+
if not isinstance(function, (MCPServer, MCPToolDefinition)) # we don't need to serialize MCP types
|
|
85
87
|
]
|
|
86
88
|
if isinstance(function_definitions, list)
|
|
87
89
|
else []
|
|
@@ -147,7 +149,13 @@ class BaseInlinePromptNodeDisplay(BaseNodeDisplay[_InlinePromptNodeType], Generi
|
|
|
147
149
|
)
|
|
148
150
|
vellum_variable_type = infer_vellum_variable_type(variable_value)
|
|
149
151
|
node_inputs.append(node_input)
|
|
150
|
-
prompt_inputs.append(
|
|
152
|
+
prompt_inputs.append(
|
|
153
|
+
VellumVariable(
|
|
154
|
+
id=str(node_input.id),
|
|
155
|
+
key=variable_name,
|
|
156
|
+
type=vellum_variable_type,
|
|
157
|
+
)
|
|
158
|
+
)
|
|
151
159
|
|
|
152
160
|
return node_inputs, prompt_inputs
|
|
153
161
|
|
|
@@ -14,7 +14,7 @@ from vellum_ee.workflows.display.nodes.utils import raise_if_descriptor
|
|
|
14
14
|
from vellum_ee.workflows.display.nodes.vellum.utils import create_node_input
|
|
15
15
|
from vellum_ee.workflows.display.types import WorkflowDisplayContext
|
|
16
16
|
from vellum_ee.workflows.display.utils.exceptions import NodeValidationError
|
|
17
|
-
from vellum_ee.workflows.display.utils.vellum import infer_vellum_variable_type
|
|
17
|
+
from vellum_ee.workflows.display.utils.vellum import compile_descriptor_annotation, infer_vellum_variable_type
|
|
18
18
|
from vellum_ee.workflows.display.vellum import NodeInput
|
|
19
19
|
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
|
20
20
|
|
|
@@ -111,20 +111,23 @@ class BaseInlineSubworkflowNodeDisplay(
|
|
|
111
111
|
for variable_name, variable_value in subworkflow_entries
|
|
112
112
|
]
|
|
113
113
|
node_inputs_by_key = {node_input.key: node_input for node_input in node_inputs}
|
|
114
|
-
workflow_inputs = [
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
114
|
+
workflow_inputs = []
|
|
115
|
+
for descriptor in subworkflow_inputs_class:
|
|
116
|
+
schema = compile_descriptor_annotation(descriptor)
|
|
117
|
+
workflow_inputs.append(
|
|
118
|
+
VellumVariable(
|
|
119
|
+
id=node_inputs_by_key[descriptor.name].id,
|
|
120
|
+
key=descriptor.name,
|
|
121
|
+
type=infer_vellum_variable_type(descriptor),
|
|
122
|
+
required=descriptor.instance is undefined,
|
|
123
|
+
default=(
|
|
124
|
+
primitive_to_vellum_value(descriptor.instance).dict()
|
|
125
|
+
if descriptor.instance is not undefined
|
|
126
|
+
else None
|
|
127
|
+
),
|
|
128
|
+
schema=schema,
|
|
129
|
+
)
|
|
125
130
|
)
|
|
126
|
-
for descriptor in subworkflow_inputs_class
|
|
127
|
-
]
|
|
128
131
|
|
|
129
132
|
return node_inputs, workflow_inputs
|
|
130
133
|
|
|
@@ -17,6 +17,7 @@ _MapNodeType = TypeVar("_MapNodeType", bound=MapNode)
|
|
|
17
17
|
|
|
18
18
|
class BaseMapNodeDisplay(BaseAdornmentNodeDisplay[_MapNodeType], Generic[_MapNodeType]):
|
|
19
19
|
__serializable_inputs__ = {MapNode.items} # type: ignore[misc]
|
|
20
|
+
__unserializable_attributes__ = {MapNode.subworkflow, MapNode.max_concurrency} # type: ignore[misc]
|
|
20
21
|
|
|
21
22
|
def serialize(
|
|
22
23
|
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **_kwargs
|
|
@@ -89,6 +90,7 @@ class BaseMapNodeDisplay(BaseAdornmentNodeDisplay[_MapNodeType], Generic[_MapNod
|
|
|
89
90
|
"item_input_id": item_workflow_input_id,
|
|
90
91
|
"index_input_id": index_workflow_input_id,
|
|
91
92
|
},
|
|
93
|
+
"attributes": self._serialize_attributes(display_context),
|
|
92
94
|
**self.serialize_generic_fields(display_context, exclude=["outputs"]),
|
|
93
95
|
}
|
|
94
96
|
|
|
@@ -1,20 +1,35 @@
|
|
|
1
|
-
|
|
1
|
+
import warnings
|
|
2
|
+
from typing import Any, ClassVar, Dict, Generic, Optional, TypeVar, Union, cast
|
|
2
3
|
|
|
3
4
|
from vellum.workflows.nodes import NoteNode
|
|
4
5
|
from vellum.workflows.types.core import JsonObject
|
|
5
6
|
from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
|
|
7
|
+
from vellum_ee.workflows.display.nodes.utils import raise_if_descriptor
|
|
6
8
|
from vellum_ee.workflows.display.types import WorkflowDisplayContext
|
|
7
9
|
|
|
8
10
|
_NoteNodeType = TypeVar("_NoteNodeType", bound=NoteNode)
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
class BaseNoteNodeDisplay(BaseNodeDisplay[_NoteNodeType], Generic[_NoteNodeType]):
|
|
14
|
+
# Deprecated: Define text and style on the node class instead. Will be removed in v2.0.0.
|
|
12
15
|
text: ClassVar[str] = ""
|
|
13
16
|
style: ClassVar[Union[Dict[str, Any], None]] = None
|
|
14
17
|
|
|
15
18
|
def serialize(self, display_context: WorkflowDisplayContext, **kwargs: Any) -> JsonObject:
|
|
16
19
|
del kwargs # Unused parameters
|
|
17
20
|
node_id = self.node_id
|
|
21
|
+
node = self._node
|
|
22
|
+
|
|
23
|
+
text = raise_if_descriptor(node.text) or ""
|
|
24
|
+
style = cast(Optional[Dict[str, Any]], raise_if_descriptor(node.style)) or None
|
|
25
|
+
|
|
26
|
+
if "text" in self.__class__.__dict__ or "style" in self.__class__.__dict__:
|
|
27
|
+
warnings.warn(
|
|
28
|
+
"Defining 'text' and 'style' on the display class is deprecated. "
|
|
29
|
+
"Define them on the node class instead. Will be removed in v2.0.0.",
|
|
30
|
+
DeprecationWarning,
|
|
31
|
+
stacklevel=2,
|
|
32
|
+
)
|
|
18
33
|
|
|
19
34
|
return {
|
|
20
35
|
"id": str(node_id),
|
|
@@ -22,8 +37,8 @@ class BaseNoteNodeDisplay(BaseNodeDisplay[_NoteNodeType], Generic[_NoteNodeType]
|
|
|
22
37
|
"inputs": [],
|
|
23
38
|
"data": {
|
|
24
39
|
"label": self.label,
|
|
25
|
-
"text":
|
|
26
|
-
"style":
|
|
40
|
+
"text": text,
|
|
41
|
+
"style": style,
|
|
27
42
|
},
|
|
28
43
|
**self.serialize_generic_fields(display_context, exclude=["outputs"]),
|
|
29
44
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
from uuid import UUID
|
|
2
2
|
from typing import Generic, Optional, TypeVar
|
|
3
3
|
|
|
4
|
+
from vellum.client import Vellum as VellumClient
|
|
5
|
+
from vellum.utils.uuid import is_valid_uuid
|
|
4
6
|
from vellum.workflows.inputs.base import BaseInputs
|
|
5
7
|
from vellum.workflows.nodes import SubworkflowDeploymentNode
|
|
6
8
|
from vellum.workflows.types.core import JsonObject
|
|
7
|
-
from vellum.workflows.utils.uuids import uuid4_from_hash
|
|
8
9
|
from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
|
|
10
|
+
from vellum_ee.workflows.display.nodes.types import NodeOutputDisplay
|
|
9
11
|
from vellum_ee.workflows.display.nodes.utils import raise_if_descriptor
|
|
10
12
|
from vellum_ee.workflows.display.nodes.vellum.utils import create_node_input
|
|
11
13
|
from vellum_ee.workflows.display.types import WorkflowDisplayContext
|
|
@@ -18,6 +20,37 @@ class BaseSubworkflowDeploymentNodeDisplay(
|
|
|
18
20
|
):
|
|
19
21
|
__serializable_inputs__ = {SubworkflowDeploymentNode.subworkflow_inputs}
|
|
20
22
|
|
|
23
|
+
_deployment_id: Optional[str] = None
|
|
24
|
+
_release_tag: Optional[str] = None
|
|
25
|
+
|
|
26
|
+
def build(self, client: VellumClient) -> None:
|
|
27
|
+
node = self._node
|
|
28
|
+
deployment_descriptor_id = str(raise_if_descriptor(node.deployment))
|
|
29
|
+
self._release_tag = raise_if_descriptor(node.release_tag)
|
|
30
|
+
|
|
31
|
+
deployment_release = client.workflow_deployments.retrieve_workflow_deployment_release(
|
|
32
|
+
id=deployment_descriptor_id,
|
|
33
|
+
release_id_or_release_tag=self._release_tag,
|
|
34
|
+
)
|
|
35
|
+
self._deployment_id = str(deployment_release.deployment.id)
|
|
36
|
+
output_variables_by_key = {var.key: var for var in deployment_release.workflow_version.output_variables}
|
|
37
|
+
|
|
38
|
+
for output in node.Outputs:
|
|
39
|
+
original_output_display = self.output_display.get(output)
|
|
40
|
+
if original_output_display and not original_output_display._is_implicit:
|
|
41
|
+
continue
|
|
42
|
+
|
|
43
|
+
output_variable = output_variables_by_key.get(output.name)
|
|
44
|
+
if not output_variable or not is_valid_uuid(output_variable.id):
|
|
45
|
+
continue
|
|
46
|
+
|
|
47
|
+
output_id = UUID(output_variable.id)
|
|
48
|
+
self.output_display[output] = NodeOutputDisplay(
|
|
49
|
+
id=output_id,
|
|
50
|
+
name=output.name,
|
|
51
|
+
)
|
|
52
|
+
self._node.__output_ids__[output.name] = output_id
|
|
53
|
+
|
|
21
54
|
def serialize(
|
|
22
55
|
self, display_context: WorkflowDisplayContext, error_output_id: Optional[UUID] = None, **_kwargs
|
|
23
56
|
) -> JsonObject:
|
|
@@ -45,16 +78,6 @@ class BaseSubworkflowDeploymentNodeDisplay(
|
|
|
45
78
|
for variable_name, variable_value in input_items
|
|
46
79
|
]
|
|
47
80
|
|
|
48
|
-
deployment_descriptor_id = str(raise_if_descriptor(node.deployment))
|
|
49
|
-
try:
|
|
50
|
-
deployment = display_context.client.workflow_deployments.retrieve(
|
|
51
|
-
id=deployment_descriptor_id,
|
|
52
|
-
)
|
|
53
|
-
deployment_id = str(deployment.id)
|
|
54
|
-
except Exception as e:
|
|
55
|
-
display_context.add_error(e)
|
|
56
|
-
deployment_id = str(uuid4_from_hash(deployment_descriptor_id))
|
|
57
|
-
|
|
58
81
|
return {
|
|
59
82
|
"id": str(node_id),
|
|
60
83
|
"type": "SUBWORKFLOW",
|
|
@@ -65,8 +88,8 @@ class BaseSubworkflowDeploymentNodeDisplay(
|
|
|
65
88
|
"source_handle_id": str(self.get_source_handle_id(display_context.port_displays)),
|
|
66
89
|
"target_handle_id": str(self.get_target_handle_id()),
|
|
67
90
|
"variant": "DEPLOYMENT",
|
|
68
|
-
"workflow_deployment_id":
|
|
69
|
-
"release_tag":
|
|
91
|
+
"workflow_deployment_id": self._deployment_id,
|
|
92
|
+
"release_tag": self._release_tag,
|
|
70
93
|
},
|
|
71
|
-
**self.serialize_generic_fields(display_context
|
|
94
|
+
**self.serialize_generic_fields(display_context),
|
|
72
95
|
}
|
|
@@ -6,6 +6,7 @@ from vellum.client.core.api_error import ApiError
|
|
|
6
6
|
from vellum.workflows.environment import EnvironmentVariables
|
|
7
7
|
from vellum.workflows.nodes.displayable.code_execution_node.node import CodeExecutionNode
|
|
8
8
|
from vellum.workflows.references.vellum_secret import VellumSecretReference
|
|
9
|
+
from vellum.workflows.state.base import BaseState
|
|
9
10
|
from vellum.workflows.workflows.base import BaseWorkflow
|
|
10
11
|
from vellum_ee.workflows.display.nodes.vellum.code_execution_node import BaseCodeExecutionNodeDisplay
|
|
11
12
|
from vellum_ee.workflows.display.utils.exceptions import NodeValidationError
|
|
@@ -217,10 +218,13 @@ def test_serialize_node__with_environment_variable_references():
|
|
|
217
218
|
assert other_config_input["value"]["combinator"] == "OR"
|
|
218
219
|
assert len(other_config_input["value"]["rules"]) == 1
|
|
219
220
|
assert other_config_input["value"]["rules"][0]["type"] == "CONSTANT_VALUE"
|
|
220
|
-
# The nested dict should contain the environment variable reference
|
|
221
221
|
nested_data = other_config_input["value"]["rules"][0]["data"]
|
|
222
222
|
assert nested_data["type"] == "JSON"
|
|
223
|
-
assert "
|
|
223
|
+
assert nested_data["value"]["type"] == "DICTIONARY_REFERENCE"
|
|
224
|
+
assert len(nested_data["value"]["entries"]) == 1
|
|
225
|
+
assert nested_data["value"]["entries"][0]["key"] == "nested_key"
|
|
226
|
+
assert nested_data["value"]["entries"][0]["value"]["type"] == "ENVIRONMENT_VARIABLE"
|
|
227
|
+
assert nested_data["value"]["entries"][0]["value"]["environment_variable"] == "NESTED_KEY"
|
|
224
228
|
|
|
225
229
|
|
|
226
230
|
def test_serialize_node__with_non_exist_code_input_path_with_dry_run():
|
|
@@ -303,6 +307,22 @@ def test_serialize_node__with_non_exist_code_input_path_with_dry_run():
|
|
|
303
307
|
},
|
|
304
308
|
"ports": [{"id": "dc9edb2e-4392-4a2c-ab92-cc1b9c0cbd53", "name": "default", "type": "DEFAULT"}],
|
|
305
309
|
"trigger": {"id": "66e7ef63-518b-40e7-911a-e38e8bcaec81", "merge_behavior": "AWAIT_ANY"},
|
|
310
|
+
"outputs": [
|
|
311
|
+
{
|
|
312
|
+
"id": "98cae9b9-45cc-4897-a0f5-df250b56c00d",
|
|
313
|
+
"name": "result",
|
|
314
|
+
"schema": {"type": "string"},
|
|
315
|
+
"type": "STRING",
|
|
316
|
+
"value": None,
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
"id": "66c06c97-a9d1-4abf-840f-3f6c29709612",
|
|
320
|
+
"name": "log",
|
|
321
|
+
"schema": {"type": "string"},
|
|
322
|
+
"type": "STRING",
|
|
323
|
+
"value": None,
|
|
324
|
+
},
|
|
325
|
+
],
|
|
306
326
|
},
|
|
307
327
|
],
|
|
308
328
|
"edges": [
|
|
@@ -326,3 +346,43 @@ def test_serialize_node__with_non_exist_code_input_path_with_dry_run():
|
|
|
326
346
|
"state_variables": [],
|
|
327
347
|
"output_variables": [],
|
|
328
348
|
}
|
|
349
|
+
|
|
350
|
+
|
|
351
|
+
def test_serialize_node__with_custom_output_type():
|
|
352
|
+
# GIVEN a code node with a custom output type
|
|
353
|
+
class MyNode(CodeExecutionNode[BaseState, dict[str, int]]):
|
|
354
|
+
code = """\
|
|
355
|
+
return {
|
|
356
|
+
"hello": 1,
|
|
357
|
+
}
|
|
358
|
+
"""
|
|
359
|
+
|
|
360
|
+
# AND a workflow with the code node
|
|
361
|
+
class Workflow(BaseWorkflow):
|
|
362
|
+
graph = MyNode
|
|
363
|
+
|
|
364
|
+
# WHEN we serialize the workflow
|
|
365
|
+
workflow_display = get_workflow_display(workflow_class=Workflow)
|
|
366
|
+
serialized_workflow: dict = workflow_display.serialize()
|
|
367
|
+
|
|
368
|
+
# THEN the node's outputs should serialize correctly
|
|
369
|
+
my_code_execution_node = next(
|
|
370
|
+
node for node in serialized_workflow["workflow_raw_data"]["nodes"] if node["type"] == "CODE_EXECUTION"
|
|
371
|
+
)
|
|
372
|
+
assert my_code_execution_node["outputs"] == [
|
|
373
|
+
{
|
|
374
|
+
"id": "01de8e8b-5e0e-4344-93b0-e002bbaed840",
|
|
375
|
+
"name": "result",
|
|
376
|
+
"value": None,
|
|
377
|
+
"type": "JSON",
|
|
378
|
+
"schema": {"type": "object", "additionalProperties": {"type": "integer"}},
|
|
379
|
+
},
|
|
380
|
+
{
|
|
381
|
+
"id": "64bf62e0-adc7-48cc-b689-8bf9b7e4eeef",
|
|
382
|
+
"name": "log",
|
|
383
|
+
"value": None,
|
|
384
|
+
"type": "STRING",
|
|
385
|
+
"schema": {"type": "string"},
|
|
386
|
+
},
|
|
387
|
+
]
|
|
388
|
+
assert my_code_execution_node["data"]["output_type"] == "JSON"
|