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,11 +1,13 @@
|
|
|
1
1
|
from dataclasses import asdict, is_dataclass
|
|
2
2
|
import inspect
|
|
3
|
+
import logging
|
|
3
4
|
from uuid import UUID
|
|
4
|
-
from typing import TYPE_CHECKING, Any, Dict, List, Optional, cast
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Set, Type, Union, cast, get_args, get_origin
|
|
5
6
|
|
|
6
7
|
from pydantic import BaseModel
|
|
7
8
|
|
|
8
9
|
from vellum.client.types.logical_operator import LogicalOperator
|
|
10
|
+
from vellum.utils.uuid import is_valid_uuid
|
|
9
11
|
from vellum.workflows.constants import undefined
|
|
10
12
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
|
11
13
|
from vellum.workflows.expressions.accessor import AccessorExpression
|
|
@@ -25,8 +27,10 @@ from vellum.workflows.expressions.equals import EqualsExpression
|
|
|
25
27
|
from vellum.workflows.expressions.greater_than import GreaterThanExpression
|
|
26
28
|
from vellum.workflows.expressions.greater_than_or_equal_to import GreaterThanOrEqualToExpression
|
|
27
29
|
from vellum.workflows.expressions.in_ import InExpression
|
|
30
|
+
from vellum.workflows.expressions.is_blank import IsBlankExpression
|
|
28
31
|
from vellum.workflows.expressions.is_error import IsErrorExpression
|
|
29
32
|
from vellum.workflows.expressions.is_nil import IsNilExpression
|
|
33
|
+
from vellum.workflows.expressions.is_not_blank import IsNotBlankExpression
|
|
30
34
|
from vellum.workflows.expressions.is_not_nil import IsNotNilExpression
|
|
31
35
|
from vellum.workflows.expressions.is_not_null import IsNotNullExpression
|
|
32
36
|
from vellum.workflows.expressions.is_not_undefined import IsNotUndefinedExpression
|
|
@@ -40,6 +44,7 @@ from vellum.workflows.expressions.not_between import NotBetweenExpression
|
|
|
40
44
|
from vellum.workflows.expressions.not_in import NotInExpression
|
|
41
45
|
from vellum.workflows.expressions.or_ import OrExpression
|
|
42
46
|
from vellum.workflows.expressions.parse_json import ParseJsonExpression
|
|
47
|
+
from vellum.workflows.inputs.base import BaseInputs
|
|
43
48
|
from vellum.workflows.nodes.bases.base import BaseNode
|
|
44
49
|
from vellum.workflows.nodes.displayable.bases.utils import primitive_to_vellum_value
|
|
45
50
|
from vellum.workflows.nodes.utils import get_unadorned_node
|
|
@@ -52,16 +57,24 @@ from vellum.workflows.references.state_value import StateValueReference
|
|
|
52
57
|
from vellum.workflows.references.trigger import TriggerAttributeReference
|
|
53
58
|
from vellum.workflows.references.vellum_secret import VellumSecretReference
|
|
54
59
|
from vellum.workflows.references.workflow_input import WorkflowInputReference
|
|
60
|
+
from vellum.workflows.state.base import BaseState
|
|
55
61
|
from vellum.workflows.types.core import JsonArray, JsonObject
|
|
56
62
|
from vellum.workflows.types.generics import is_workflow_class
|
|
57
63
|
from vellum.workflows.utils.files import virtual_open
|
|
58
|
-
from vellum.workflows.utils.functions import compile_function_definition
|
|
64
|
+
from vellum.workflows.utils.functions import compile_function_definition, compile_inline_workflow_function_definition
|
|
59
65
|
from vellum.workflows.utils.uuids import uuid4_from_hash
|
|
60
|
-
from
|
|
66
|
+
from vellum.workflows.workflows.base import BaseWorkflow
|
|
67
|
+
from vellum_ee.workflows.display.utils.exceptions import (
|
|
68
|
+
InvalidInputReferenceError,
|
|
69
|
+
InvalidOutputReferenceError,
|
|
70
|
+
UnsupportedSerializationException,
|
|
71
|
+
)
|
|
61
72
|
|
|
62
73
|
if TYPE_CHECKING:
|
|
63
74
|
from vellum_ee.workflows.display.types import WorkflowDisplayContext
|
|
64
75
|
|
|
76
|
+
logger = logging.getLogger(__name__)
|
|
77
|
+
|
|
65
78
|
|
|
66
79
|
def convert_descriptor_to_operator(descriptor: BaseDescriptor) -> LogicalOperator:
|
|
67
80
|
if isinstance(descriptor, EqualsExpression):
|
|
@@ -94,6 +107,10 @@ def convert_descriptor_to_operator(descriptor: BaseDescriptor) -> LogicalOperato
|
|
|
94
107
|
return "null"
|
|
95
108
|
elif isinstance(descriptor, (IsNotNullExpression, IsNotNilExpression, IsNotUndefinedExpression)):
|
|
96
109
|
return "notNull"
|
|
110
|
+
elif isinstance(descriptor, IsBlankExpression):
|
|
111
|
+
return "blank"
|
|
112
|
+
elif isinstance(descriptor, IsNotBlankExpression):
|
|
113
|
+
return "notBlank"
|
|
97
114
|
elif isinstance(descriptor, InExpression):
|
|
98
115
|
return "in"
|
|
99
116
|
elif isinstance(descriptor, NotInExpression):
|
|
@@ -119,28 +136,40 @@ def convert_descriptor_to_operator(descriptor: BaseDescriptor) -> LogicalOperato
|
|
|
119
136
|
elif isinstance(descriptor, ConcatExpression):
|
|
120
137
|
return "concat"
|
|
121
138
|
else:
|
|
122
|
-
raise
|
|
139
|
+
raise UnsupportedSerializationException(f"Unsupported descriptor type: {descriptor}")
|
|
123
140
|
|
|
124
141
|
|
|
125
142
|
def get_child_descriptor(value: LazyReference, display_context: "WorkflowDisplayContext") -> BaseDescriptor:
|
|
126
143
|
if isinstance(value._get, str):
|
|
127
144
|
reference_parts = value._get.split(".")
|
|
128
145
|
if len(reference_parts) < 3:
|
|
129
|
-
raise
|
|
146
|
+
raise InvalidOutputReferenceError(
|
|
147
|
+
f"Failed to parse lazy reference: {value._get}. Only Node and Workflow Output references are supported."
|
|
148
|
+
)
|
|
130
149
|
|
|
131
150
|
output_name = reference_parts[-1]
|
|
132
151
|
nested_class_name = reference_parts[-2]
|
|
133
152
|
if nested_class_name != "Outputs":
|
|
134
|
-
raise
|
|
135
|
-
f"Failed to parse lazy reference: {value._get}. Outputs are the only
|
|
153
|
+
raise InvalidOutputReferenceError(
|
|
154
|
+
f"Failed to parse lazy reference: {value._get}. Outputs are the only supported references."
|
|
136
155
|
)
|
|
137
156
|
|
|
138
|
-
|
|
157
|
+
reference_class_name = ".".join(reference_parts[:-2])
|
|
158
|
+
|
|
159
|
+
# First try to find a node with the matching name
|
|
139
160
|
for node in display_context.global_node_displays.keys():
|
|
140
|
-
if node.__name__ ==
|
|
161
|
+
if node.__name__ == reference_class_name:
|
|
141
162
|
return getattr(node.Outputs, output_name)
|
|
142
163
|
|
|
143
|
-
|
|
164
|
+
# If no node found, check if it's a reference to the current workflow's outputs
|
|
165
|
+
workflow_class = display_context.workflow_display_class.infer_workflow_class()
|
|
166
|
+
if workflow_class.__name__ == reference_class_name:
|
|
167
|
+
return getattr(workflow_class.Outputs, output_name)
|
|
168
|
+
|
|
169
|
+
raise InvalidOutputReferenceError(
|
|
170
|
+
f"Failed to parse lazy reference: {value._get}. "
|
|
171
|
+
f"Could not find node or workflow class '{reference_class_name}'."
|
|
172
|
+
)
|
|
144
173
|
|
|
145
174
|
return value._get()
|
|
146
175
|
|
|
@@ -161,13 +190,39 @@ def _get_pydantic_model_definition(model_class: type) -> Optional[JsonObject]:
|
|
|
161
190
|
}
|
|
162
191
|
|
|
163
192
|
|
|
193
|
+
BinaryExpression = Union[
|
|
194
|
+
AddExpression,
|
|
195
|
+
AndExpression,
|
|
196
|
+
BeginsWithExpression,
|
|
197
|
+
CoalesceExpression,
|
|
198
|
+
ConcatExpression,
|
|
199
|
+
ContainsExpression,
|
|
200
|
+
DoesNotBeginWithExpression,
|
|
201
|
+
DoesNotContainExpression,
|
|
202
|
+
DoesNotEndWithExpression,
|
|
203
|
+
DoesNotEqualExpression,
|
|
204
|
+
EndsWithExpression,
|
|
205
|
+
EqualsExpression,
|
|
206
|
+
GreaterThanExpression,
|
|
207
|
+
GreaterThanOrEqualToExpression,
|
|
208
|
+
InExpression,
|
|
209
|
+
LessThanExpression,
|
|
210
|
+
LessThanOrEqualToExpression,
|
|
211
|
+
MinusExpression,
|
|
212
|
+
NotInExpression,
|
|
213
|
+
OrExpression,
|
|
214
|
+
]
|
|
215
|
+
|
|
216
|
+
|
|
164
217
|
def _serialize_condition(
|
|
165
218
|
executable_id: UUID, display_context: "WorkflowDisplayContext", condition: BaseDescriptor
|
|
166
219
|
) -> JsonObject:
|
|
167
220
|
if isinstance(
|
|
168
221
|
condition,
|
|
169
222
|
(
|
|
223
|
+
IsBlankExpression,
|
|
170
224
|
IsErrorExpression,
|
|
225
|
+
IsNotBlankExpression,
|
|
171
226
|
IsNullExpression,
|
|
172
227
|
IsNotNullExpression,
|
|
173
228
|
IsNilExpression,
|
|
@@ -198,28 +253,7 @@ def _serialize_condition(
|
|
|
198
253
|
}
|
|
199
254
|
elif isinstance(
|
|
200
255
|
condition,
|
|
201
|
-
(
|
|
202
|
-
AddExpression,
|
|
203
|
-
AndExpression,
|
|
204
|
-
BeginsWithExpression,
|
|
205
|
-
CoalesceExpression,
|
|
206
|
-
ConcatExpression,
|
|
207
|
-
ContainsExpression,
|
|
208
|
-
DoesNotBeginWithExpression,
|
|
209
|
-
DoesNotContainExpression,
|
|
210
|
-
DoesNotEndWithExpression,
|
|
211
|
-
DoesNotEqualExpression,
|
|
212
|
-
EndsWithExpression,
|
|
213
|
-
EqualsExpression,
|
|
214
|
-
GreaterThanExpression,
|
|
215
|
-
GreaterThanOrEqualToExpression,
|
|
216
|
-
InExpression,
|
|
217
|
-
LessThanExpression,
|
|
218
|
-
LessThanOrEqualToExpression,
|
|
219
|
-
MinusExpression,
|
|
220
|
-
NotInExpression,
|
|
221
|
-
OrExpression,
|
|
222
|
-
),
|
|
256
|
+
get_args(BinaryExpression),
|
|
223
257
|
):
|
|
224
258
|
lhs = serialize_value(executable_id, display_context, condition._lhs)
|
|
225
259
|
rhs = serialize_value(executable_id, display_context, condition._rhs)
|
|
@@ -251,6 +285,55 @@ def serialize_key(key: Any) -> str:
|
|
|
251
285
|
return str(key)
|
|
252
286
|
|
|
253
287
|
|
|
288
|
+
def _extract_node_classes_from_object(obj: Any, seen: Set[Type[BaseNode]], node_classes: List[Type[BaseNode]]) -> None:
|
|
289
|
+
"""
|
|
290
|
+
Extract BaseNode subclasses from an object, handling classes, instances, and typing constructs.
|
|
291
|
+
|
|
292
|
+
Modifies seen and node_classes in place.
|
|
293
|
+
"""
|
|
294
|
+
if isinstance(obj, str):
|
|
295
|
+
return
|
|
296
|
+
|
|
297
|
+
if inspect.isclass(obj) and issubclass(obj, BaseNode) and obj is not BaseNode:
|
|
298
|
+
if obj not in seen:
|
|
299
|
+
seen.add(obj)
|
|
300
|
+
node_classes.append(obj)
|
|
301
|
+
return
|
|
302
|
+
|
|
303
|
+
if isinstance(obj, BaseNode):
|
|
304
|
+
obj_class = obj.__class__
|
|
305
|
+
if obj_class not in seen:
|
|
306
|
+
seen.add(obj_class)
|
|
307
|
+
node_classes.append(obj_class)
|
|
308
|
+
return
|
|
309
|
+
|
|
310
|
+
origin = get_origin(obj)
|
|
311
|
+
if origin is not None:
|
|
312
|
+
for arg in get_args(obj):
|
|
313
|
+
_extract_node_classes_from_object(arg, seen, node_classes)
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
def _get_node_references_in_callable(func: Any) -> List[Type[BaseNode]]:
|
|
317
|
+
"""
|
|
318
|
+
Check if a callable actually references any BaseNode subclasses in its body.
|
|
319
|
+
|
|
320
|
+
Uses inspect.getclosurevars to detect globals/nonlocals referenced by the function.
|
|
321
|
+
|
|
322
|
+
Returns a list of node classes found in the callable's referenced scope.
|
|
323
|
+
"""
|
|
324
|
+
node_classes: List[Type[BaseNode]] = []
|
|
325
|
+
seen: Set[Type[BaseNode]] = set()
|
|
326
|
+
|
|
327
|
+
try:
|
|
328
|
+
closure_vars = inspect.getclosurevars(func)
|
|
329
|
+
for obj in list(closure_vars.globals.values()) + list(closure_vars.nonlocals.values()):
|
|
330
|
+
_extract_node_classes_from_object(obj, seen, node_classes)
|
|
331
|
+
except (TypeError, ValueError):
|
|
332
|
+
pass
|
|
333
|
+
|
|
334
|
+
return node_classes
|
|
335
|
+
|
|
336
|
+
|
|
254
337
|
def serialize_value(executable_id: UUID, display_context: "WorkflowDisplayContext", value: Any) -> Optional[JsonObject]:
|
|
255
338
|
"""
|
|
256
339
|
Serialize a value to a JSON object. Returns `None` if the value resolves to `undefined`.
|
|
@@ -272,7 +355,12 @@ def serialize_value(executable_id: UUID, display_context: "WorkflowDisplayContex
|
|
|
272
355
|
return serialize_value(executable_id, display_context, value._value)
|
|
273
356
|
|
|
274
357
|
if isinstance(value, LazyReference):
|
|
275
|
-
|
|
358
|
+
try:
|
|
359
|
+
child_descriptor = get_child_descriptor(value, display_context)
|
|
360
|
+
except InvalidOutputReferenceError as e:
|
|
361
|
+
logger.warning("Failed to parse lazy reference '%s', skipping serialization", value.name)
|
|
362
|
+
display_context.add_validation_error(e)
|
|
363
|
+
return None
|
|
276
364
|
return serialize_value(executable_id, display_context, child_descriptor)
|
|
277
365
|
|
|
278
366
|
if isinstance(value, WorkflowInputReference):
|
|
@@ -307,6 +395,22 @@ def serialize_value(executable_id: UUID, display_context: "WorkflowDisplayContex
|
|
|
307
395
|
}
|
|
308
396
|
|
|
309
397
|
if isinstance(value, OutputReference):
|
|
398
|
+
if issubclass(value.outputs_class, BaseWorkflow.Outputs):
|
|
399
|
+
if value in display_context.workflow_output_displays:
|
|
400
|
+
workflow_output_display = display_context.workflow_output_displays[value]
|
|
401
|
+
return {
|
|
402
|
+
"type": "WORKFLOW_OUTPUT",
|
|
403
|
+
"output_variable_id": str(workflow_output_display.id),
|
|
404
|
+
}
|
|
405
|
+
return serialize_value(executable_id, display_context, value.instance)
|
|
406
|
+
|
|
407
|
+
if value not in display_context.global_node_output_displays:
|
|
408
|
+
if issubclass(value.outputs_class, BaseNode.Outputs):
|
|
409
|
+
raise InvalidOutputReferenceError(
|
|
410
|
+
f"Reference to node '{value.outputs_class.__parent_class__.__name__}' not found in graph."
|
|
411
|
+
)
|
|
412
|
+
raise InvalidOutputReferenceError(f"Reference to outputs '{value.outputs_class.__qualname__}' is invalid.")
|
|
413
|
+
|
|
310
414
|
output_display = display_context.global_node_output_displays[value]
|
|
311
415
|
|
|
312
416
|
upstream_node_class = value.outputs_class.__parent_class__
|
|
@@ -328,19 +432,10 @@ def serialize_value(executable_id: UUID, display_context: "WorkflowDisplayContex
|
|
|
328
432
|
}
|
|
329
433
|
|
|
330
434
|
if isinstance(value, EnvironmentVariableReference):
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
"type": "STRING",
|
|
336
|
-
"value": value.name,
|
|
337
|
-
},
|
|
338
|
-
}
|
|
339
|
-
else:
|
|
340
|
-
return {
|
|
341
|
-
"type": "ENVIRONMENT_VARIABLE",
|
|
342
|
-
"environment_variable": value.name,
|
|
343
|
-
}
|
|
435
|
+
return {
|
|
436
|
+
"type": "ENVIRONMENT_VARIABLE",
|
|
437
|
+
"environment_variable": value.name,
|
|
438
|
+
}
|
|
344
439
|
|
|
345
440
|
if isinstance(value, ExecutionCountReference):
|
|
346
441
|
node_class_display = display_context.global_node_displays[value.node_class]
|
|
@@ -430,6 +525,7 @@ def serialize_value(executable_id: UUID, display_context: "WorkflowDisplayContex
|
|
|
430
525
|
}
|
|
431
526
|
|
|
432
527
|
if is_workflow_class(value):
|
|
528
|
+
# Import here to avoid circular imports
|
|
433
529
|
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
|
434
530
|
|
|
435
531
|
# Pass the parent display context so the subworkflow can resolve parent workflow inputs
|
|
@@ -440,16 +536,38 @@ def serialize_value(executable_id: UUID, display_context: "WorkflowDisplayContex
|
|
|
440
536
|
serialized_value: dict = workflow_display.serialize()
|
|
441
537
|
name = serialized_value["workflow_raw_data"]["definition"]["name"]
|
|
442
538
|
description = value.__doc__ or ""
|
|
539
|
+
|
|
540
|
+
# Compile the function definition (which now handles __vellum_inputs__ and __vellum_examples__)
|
|
541
|
+
function_definition = compile_inline_workflow_function_definition(value)
|
|
542
|
+
|
|
543
|
+
# Handle __vellum_inputs__ for inline workflows (similar to function tools)
|
|
544
|
+
inputs = getattr(value, "__vellum_inputs__", {})
|
|
545
|
+
if inputs:
|
|
546
|
+
serialized_inputs = {}
|
|
547
|
+
for param_name, input_ref in inputs.items():
|
|
548
|
+
serialized_input = serialize_value(executable_id, display_context, input_ref)
|
|
549
|
+
if serialized_input is not None:
|
|
550
|
+
serialized_inputs[param_name] = serialized_input
|
|
551
|
+
|
|
552
|
+
model_data = function_definition.model_dump()
|
|
553
|
+
model_data["inputs"] = serialized_inputs
|
|
554
|
+
function_definition_data = model_data
|
|
555
|
+
else:
|
|
556
|
+
function_definition_data = function_definition.model_dump()
|
|
557
|
+
|
|
558
|
+
workflow_data: Dict[str, Any] = {
|
|
559
|
+
"type": "INLINE_WORKFLOW",
|
|
560
|
+
"name": name,
|
|
561
|
+
"description": description,
|
|
562
|
+
"definition": function_definition_data,
|
|
563
|
+
"exec_config": serialized_value,
|
|
564
|
+
}
|
|
565
|
+
|
|
443
566
|
return {
|
|
444
567
|
"type": "CONSTANT_VALUE",
|
|
445
568
|
"value": {
|
|
446
569
|
"type": "JSON",
|
|
447
|
-
"value":
|
|
448
|
-
"type": "INLINE_WORKFLOW",
|
|
449
|
-
"name": name,
|
|
450
|
-
"description": description,
|
|
451
|
-
"exec_config": serialized_value,
|
|
452
|
-
},
|
|
570
|
+
"value": workflow_data,
|
|
453
571
|
},
|
|
454
572
|
}
|
|
455
573
|
|
|
@@ -462,6 +580,15 @@ def serialize_value(executable_id: UUID, display_context: "WorkflowDisplayContex
|
|
|
462
580
|
return dict_ref
|
|
463
581
|
|
|
464
582
|
if callable(value):
|
|
583
|
+
node_references = _get_node_references_in_callable(value)
|
|
584
|
+
if node_references:
|
|
585
|
+
node_names = ", ".join(node.__name__ for node in node_references)
|
|
586
|
+
raise UnsupportedSerializationException(
|
|
587
|
+
f"Code tools cannot reference workflow nodes ({node_names}). "
|
|
588
|
+
"Consider inlining the node's run method logic directly in your function, "
|
|
589
|
+
"or use an Inline Subworkflow tool instead."
|
|
590
|
+
)
|
|
591
|
+
|
|
465
592
|
function_definition = compile_function_definition(value)
|
|
466
593
|
|
|
467
594
|
name = function_definition.name
|
|
@@ -513,3 +640,287 @@ def serialize_value(executable_id: UUID, display_context: "WorkflowDisplayContex
|
|
|
513
640
|
# If it's not any of the references we know about,
|
|
514
641
|
# then try to serialize it as a nested value
|
|
515
642
|
return _serialize_condition(executable_id, display_context, value)
|
|
643
|
+
|
|
644
|
+
|
|
645
|
+
def base_descriptor_validator(value: dict, workflow: Type[BaseWorkflow]) -> BaseDescriptor:
|
|
646
|
+
descriptor_type = value.get("type")
|
|
647
|
+
|
|
648
|
+
if descriptor_type == "CONSTANT_VALUE":
|
|
649
|
+
return _constant_value_reference_validator(value.get("value"))
|
|
650
|
+
|
|
651
|
+
if descriptor_type == "WORKFLOW_INPUT":
|
|
652
|
+
return _workflow_input_reference_validator(value.get("input_variable_id"), workflow)
|
|
653
|
+
|
|
654
|
+
if descriptor_type == "WORKFLOW_STATE":
|
|
655
|
+
return _workflow_state_reference_validator(value.get("state_variable_id"), workflow)
|
|
656
|
+
|
|
657
|
+
if descriptor_type == "NODE_OUTPUT":
|
|
658
|
+
return _node_output_reference_validator(value.get("node_id"), value.get("node_output_id"), workflow)
|
|
659
|
+
|
|
660
|
+
if descriptor_type == "EXECUTION_COUNTER":
|
|
661
|
+
return _execution_counter_reference_validator(value.get("node_id"), workflow)
|
|
662
|
+
|
|
663
|
+
if descriptor_type == "VELLUM_SECRET":
|
|
664
|
+
return _vellum_secret_reference_validator(value.get("vellum_secret_name"))
|
|
665
|
+
|
|
666
|
+
if descriptor_type == "ENVIRONMENT_VARIABLE":
|
|
667
|
+
return _environment_variable_reference_validator(value.get("environment_variable"))
|
|
668
|
+
|
|
669
|
+
if descriptor_type == "ARRAY_REFERENCE":
|
|
670
|
+
return _array_reference_validator(value.get("items"), workflow)
|
|
671
|
+
|
|
672
|
+
if descriptor_type == "DICTIONARY_REFERENCE":
|
|
673
|
+
return _dictionary_reference_validator(value.get("entries"), workflow)
|
|
674
|
+
|
|
675
|
+
if descriptor_type == "BINARY_EXPRESSION":
|
|
676
|
+
return _binary_expression_validator(value, workflow)
|
|
677
|
+
|
|
678
|
+
if descriptor_type == "UNARY_EXPRESSION":
|
|
679
|
+
return _unary_expression_validator(value, workflow)
|
|
680
|
+
|
|
681
|
+
if descriptor_type == "TERNARY_EXPRESSION":
|
|
682
|
+
return _ternary_expression_validator(value, workflow)
|
|
683
|
+
|
|
684
|
+
raise ValueError(f"Unsupported descriptor type: {descriptor_type}")
|
|
685
|
+
|
|
686
|
+
|
|
687
|
+
def _constant_value_reference_validator(constant: Any) -> ConstantValueReference:
|
|
688
|
+
if not isinstance(constant, dict):
|
|
689
|
+
raise ValueError(f"Unexpected type for constant reference: {type(constant)}")
|
|
690
|
+
|
|
691
|
+
return ConstantValueReference(constant.get("value"))
|
|
692
|
+
|
|
693
|
+
|
|
694
|
+
def _workflow_input_reference_validator(workflow_input_id: Any, workflow: Type[BaseWorkflow]) -> WorkflowInputReference:
|
|
695
|
+
inputs_class = workflow.get_inputs_class()
|
|
696
|
+
if not issubclass(inputs_class, BaseInputs):
|
|
697
|
+
raise ValueError(f"Unexpected type for inputs class: {type(inputs_class)}")
|
|
698
|
+
|
|
699
|
+
input_reference = next(
|
|
700
|
+
(
|
|
701
|
+
input
|
|
702
|
+
for input in inputs_class
|
|
703
|
+
if isinstance(input, WorkflowInputReference) and str(input.id) == str(workflow_input_id)
|
|
704
|
+
),
|
|
705
|
+
None,
|
|
706
|
+
)
|
|
707
|
+
if input_reference is None:
|
|
708
|
+
raise ValueError(f"Input reference not found: {workflow_input_id}")
|
|
709
|
+
|
|
710
|
+
return input_reference
|
|
711
|
+
|
|
712
|
+
|
|
713
|
+
def _workflow_state_reference_validator(workflow_state_id: Any, workflow: Type[BaseWorkflow]) -> StateValueReference:
|
|
714
|
+
state_class = workflow.get_state_class()
|
|
715
|
+
if not issubclass(state_class, BaseState):
|
|
716
|
+
raise ValueError(f"Unexpected type for state class: {type(state_class)}")
|
|
717
|
+
|
|
718
|
+
state_reference = next((state for state in state_class if str(state.id) == str(workflow_state_id)), None)
|
|
719
|
+
if state_reference is None:
|
|
720
|
+
raise ValueError(f"State reference not found: {workflow_state_id}")
|
|
721
|
+
|
|
722
|
+
return state_reference
|
|
723
|
+
|
|
724
|
+
|
|
725
|
+
def _node_output_reference_validator(
|
|
726
|
+
node_id: Any, node_output_id: Any, workflow: Type[BaseWorkflow]
|
|
727
|
+
) -> OutputReference:
|
|
728
|
+
if not is_valid_uuid(node_id):
|
|
729
|
+
raise ValueError(f"Unexpected type for node id: {type(node_id)}")
|
|
730
|
+
|
|
731
|
+
if not is_valid_uuid(node_output_id):
|
|
732
|
+
raise ValueError(f"Unexpected type for node output id: {type(node_output_id)}")
|
|
733
|
+
|
|
734
|
+
node_class = workflow.resolve_node_ref(node_id)
|
|
735
|
+
if not issubclass(node_class, BaseNode):
|
|
736
|
+
raise ValueError(f"Unexpected type for node class: {type(node_class)}")
|
|
737
|
+
|
|
738
|
+
output_reference = next((output for output in node_class.Outputs if str(output.id) == str(node_output_id)), None)
|
|
739
|
+
if output_reference is None:
|
|
740
|
+
raise ValueError(f"Output reference not found: {node_output_id}")
|
|
741
|
+
|
|
742
|
+
return output_reference
|
|
743
|
+
|
|
744
|
+
|
|
745
|
+
def _execution_counter_reference_validator(node_id: Any, workflow: Type[BaseWorkflow]) -> ExecutionCountReference:
|
|
746
|
+
node_class = workflow.resolve_node_ref(node_id)
|
|
747
|
+
return ExecutionCountReference(node_class)
|
|
748
|
+
|
|
749
|
+
|
|
750
|
+
def _vellum_secret_reference_validator(secret_name: Any) -> VellumSecretReference:
|
|
751
|
+
if not isinstance(secret_name, str):
|
|
752
|
+
raise ValueError(f"Unexpected type for vellum secret name: {type(secret_name)}")
|
|
753
|
+
return VellumSecretReference(secret_name)
|
|
754
|
+
|
|
755
|
+
|
|
756
|
+
def _environment_variable_reference_validator(env_var_name: Any) -> EnvironmentVariableReference:
|
|
757
|
+
if not isinstance(env_var_name, str):
|
|
758
|
+
raise ValueError(f"Unexpected type for environment variable name: {type(env_var_name)}")
|
|
759
|
+
return EnvironmentVariableReference(name=env_var_name)
|
|
760
|
+
|
|
761
|
+
|
|
762
|
+
def _array_reference_validator(items: Any, workflow: Type[BaseWorkflow]) -> ConstantValueReference:
|
|
763
|
+
if not isinstance(items, list):
|
|
764
|
+
raise ValueError(f"Unexpected type for array items: {type(items)}")
|
|
765
|
+
|
|
766
|
+
validated_items = []
|
|
767
|
+
for item in items:
|
|
768
|
+
if isinstance(item, dict):
|
|
769
|
+
validated_items.append(base_descriptor_validator(item, workflow))
|
|
770
|
+
else:
|
|
771
|
+
validated_items.append(item)
|
|
772
|
+
|
|
773
|
+
return ConstantValueReference(validated_items)
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
def _dictionary_reference_validator(entries: Any, workflow: Type[BaseWorkflow]) -> ConstantValueReference:
|
|
777
|
+
if not isinstance(entries, list):
|
|
778
|
+
raise ValueError(f"Unexpected type for dictionary entries: {type(entries)}")
|
|
779
|
+
|
|
780
|
+
validated_dict: Dict[str, Any] = {}
|
|
781
|
+
for entry in entries:
|
|
782
|
+
if not isinstance(entry, dict):
|
|
783
|
+
raise ValueError(f"Unexpected type for dictionary entry: {type(entry)}")
|
|
784
|
+
|
|
785
|
+
key = entry.get("key")
|
|
786
|
+
if not isinstance(key, str):
|
|
787
|
+
raise ValueError(f"Unexpected type for dictionary key: {type(key)}")
|
|
788
|
+
|
|
789
|
+
raw_value = entry.get("value")
|
|
790
|
+
if isinstance(raw_value, dict):
|
|
791
|
+
validated_dict[key] = base_descriptor_validator(raw_value, workflow)
|
|
792
|
+
else:
|
|
793
|
+
validated_dict[key] = raw_value
|
|
794
|
+
|
|
795
|
+
return ConstantValueReference(validated_dict)
|
|
796
|
+
|
|
797
|
+
|
|
798
|
+
UnaryExpression = Union[
|
|
799
|
+
IsBlankExpression,
|
|
800
|
+
IsErrorExpression,
|
|
801
|
+
IsNilExpression,
|
|
802
|
+
IsNotBlankExpression,
|
|
803
|
+
IsNotNilExpression,
|
|
804
|
+
IsNotNullExpression,
|
|
805
|
+
IsNotUndefinedExpression,
|
|
806
|
+
IsNullExpression,
|
|
807
|
+
IsUndefinedExpression,
|
|
808
|
+
LengthExpression,
|
|
809
|
+
ParseJsonExpression,
|
|
810
|
+
]
|
|
811
|
+
|
|
812
|
+
|
|
813
|
+
def _unary_expression_validator(unary_expression: dict, workflow: Type[BaseWorkflow]) -> UnaryExpression:
|
|
814
|
+
operator = unary_expression.get("operator")
|
|
815
|
+
raw_lhs = unary_expression.get("lhs")
|
|
816
|
+
if not isinstance(raw_lhs, dict):
|
|
817
|
+
raise ValueError(f"Unexpected type for lhs: {type(raw_lhs)}")
|
|
818
|
+
|
|
819
|
+
expression = base_descriptor_validator(raw_lhs, workflow)
|
|
820
|
+
|
|
821
|
+
if operator == "blank":
|
|
822
|
+
return IsBlankExpression(expression=expression)
|
|
823
|
+
elif operator == "notBlank":
|
|
824
|
+
return IsNotBlankExpression(expression=expression)
|
|
825
|
+
elif operator == "null":
|
|
826
|
+
return IsNullExpression(expression=expression)
|
|
827
|
+
elif operator == "notNull":
|
|
828
|
+
return IsNotNullExpression(expression=expression)
|
|
829
|
+
elif operator == "isError":
|
|
830
|
+
return IsErrorExpression(expression=expression)
|
|
831
|
+
elif operator == "length":
|
|
832
|
+
return LengthExpression(expression=expression)
|
|
833
|
+
elif operator == "parseJson":
|
|
834
|
+
return ParseJsonExpression(expression=expression)
|
|
835
|
+
|
|
836
|
+
raise ValueError(f"Unsupported unary expression operator: {operator}")
|
|
837
|
+
|
|
838
|
+
|
|
839
|
+
TernaryExpression = Union[BetweenExpression, NotBetweenExpression]
|
|
840
|
+
|
|
841
|
+
|
|
842
|
+
def _ternary_expression_validator(ternary_expression: dict, workflow: Type[BaseWorkflow]) -> TernaryExpression:
|
|
843
|
+
operator = ternary_expression.get("operator")
|
|
844
|
+
raw_base = ternary_expression.get("base")
|
|
845
|
+
if not isinstance(raw_base, dict):
|
|
846
|
+
raise ValueError(f"Unexpected type for base: {type(raw_base)}")
|
|
847
|
+
|
|
848
|
+
raw_lhs = ternary_expression.get("lhs")
|
|
849
|
+
if not isinstance(raw_lhs, dict):
|
|
850
|
+
raise ValueError(f"Unexpected type for lhs: {type(raw_lhs)}")
|
|
851
|
+
|
|
852
|
+
raw_rhs = ternary_expression.get("rhs")
|
|
853
|
+
if not isinstance(raw_rhs, dict):
|
|
854
|
+
raise ValueError(f"Unexpected type for rhs: {type(raw_rhs)}")
|
|
855
|
+
|
|
856
|
+
base = base_descriptor_validator(raw_base, workflow)
|
|
857
|
+
start = base_descriptor_validator(raw_lhs, workflow)
|
|
858
|
+
end = base_descriptor_validator(raw_rhs, workflow)
|
|
859
|
+
|
|
860
|
+
if operator == "between":
|
|
861
|
+
return BetweenExpression(value=base, start=start, end=end)
|
|
862
|
+
elif operator == "notBetween":
|
|
863
|
+
return NotBetweenExpression(value=base, start=start, end=end)
|
|
864
|
+
|
|
865
|
+
raise ValueError(f"Unsupported ternary expression operator: {operator}")
|
|
866
|
+
|
|
867
|
+
|
|
868
|
+
def _binary_expression_validator(
|
|
869
|
+
binary_expression: dict, workflow: Type[BaseWorkflow]
|
|
870
|
+
) -> Union[BinaryExpression, AccessorExpression]:
|
|
871
|
+
operator = binary_expression.get("operator")
|
|
872
|
+
raw_lhs = binary_expression.get("lhs")
|
|
873
|
+
if not isinstance(raw_lhs, dict):
|
|
874
|
+
raise ValueError(f"Unexpected type for lhs: {type(raw_lhs)}")
|
|
875
|
+
|
|
876
|
+
raw_rhs = binary_expression.get("rhs")
|
|
877
|
+
if not isinstance(raw_rhs, dict):
|
|
878
|
+
raise ValueError(f"Unexpected type for rhs: {type(raw_rhs)}")
|
|
879
|
+
|
|
880
|
+
lhs = base_descriptor_validator(raw_lhs, workflow)
|
|
881
|
+
rhs = base_descriptor_validator(raw_rhs, workflow)
|
|
882
|
+
|
|
883
|
+
if operator in ("=", "=="):
|
|
884
|
+
return EqualsExpression(lhs=lhs, rhs=rhs)
|
|
885
|
+
elif operator == "!=":
|
|
886
|
+
return DoesNotEqualExpression(lhs=lhs, rhs=rhs)
|
|
887
|
+
elif operator == "<":
|
|
888
|
+
return LessThanExpression(lhs=lhs, rhs=rhs)
|
|
889
|
+
elif operator == ">":
|
|
890
|
+
return GreaterThanExpression(lhs=lhs, rhs=rhs)
|
|
891
|
+
elif operator == "<=":
|
|
892
|
+
return LessThanOrEqualToExpression(lhs=lhs, rhs=rhs)
|
|
893
|
+
elif operator == ">=":
|
|
894
|
+
return GreaterThanOrEqualToExpression(lhs=lhs, rhs=rhs)
|
|
895
|
+
elif operator == "contains":
|
|
896
|
+
return ContainsExpression(lhs=lhs, rhs=rhs)
|
|
897
|
+
elif operator == "beginsWith":
|
|
898
|
+
return BeginsWithExpression(lhs=lhs, rhs=rhs)
|
|
899
|
+
elif operator == "endsWith":
|
|
900
|
+
return EndsWithExpression(lhs=lhs, rhs=rhs)
|
|
901
|
+
elif operator == "doesNotContain":
|
|
902
|
+
return DoesNotContainExpression(lhs=lhs, rhs=rhs)
|
|
903
|
+
elif operator == "doesNotBeginWith":
|
|
904
|
+
return DoesNotBeginWithExpression(lhs=lhs, rhs=rhs)
|
|
905
|
+
elif operator == "doesNotEndWith":
|
|
906
|
+
return DoesNotEndWithExpression(lhs=lhs, rhs=rhs)
|
|
907
|
+
elif operator == "in":
|
|
908
|
+
return InExpression(lhs=lhs, rhs=rhs)
|
|
909
|
+
elif operator == "notIn":
|
|
910
|
+
return NotInExpression(lhs=lhs, rhs=rhs)
|
|
911
|
+
elif operator == "and":
|
|
912
|
+
return AndExpression(lhs=lhs, rhs=rhs)
|
|
913
|
+
elif operator == "or":
|
|
914
|
+
return OrExpression(lhs=lhs, rhs=rhs)
|
|
915
|
+
elif operator == "coalesce":
|
|
916
|
+
return CoalesceExpression(lhs=lhs, rhs=rhs)
|
|
917
|
+
elif operator == "+":
|
|
918
|
+
return AddExpression(lhs=lhs, rhs=rhs)
|
|
919
|
+
elif operator == "-":
|
|
920
|
+
return MinusExpression(lhs=lhs, rhs=rhs)
|
|
921
|
+
elif operator == "concat":
|
|
922
|
+
return ConcatExpression(lhs=lhs, rhs=rhs)
|
|
923
|
+
elif operator == "accessField":
|
|
924
|
+
return AccessorExpression(base=lhs, field=rhs)
|
|
925
|
+
|
|
926
|
+
raise ValueError(f"Unsupported binary expression operator: {operator}")
|