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
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
"""Tests for ChatMessageTrigger."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from typing import List, Optional
|
|
5
|
+
|
|
6
|
+
from pydantic import Field
|
|
7
|
+
|
|
8
|
+
from vellum.client.types import (
|
|
9
|
+
ArrayChatMessageContent,
|
|
10
|
+
ArrayChatMessageContentItem,
|
|
11
|
+
ChatMessage,
|
|
12
|
+
ImageChatMessageContent,
|
|
13
|
+
StringChatMessageContent,
|
|
14
|
+
StringVellumValue,
|
|
15
|
+
VellumImage,
|
|
16
|
+
)
|
|
17
|
+
from vellum.workflows.inputs.base import BaseInputs
|
|
18
|
+
from vellum.workflows.nodes.bases.base import BaseNode
|
|
19
|
+
from vellum.workflows.outputs import BaseOutputs
|
|
20
|
+
from vellum.workflows.state.base import BaseState
|
|
21
|
+
from vellum.workflows.triggers.chat_message import ChatMessageTrigger
|
|
22
|
+
from vellum.workflows.workflows.base import BaseWorkflow
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ChatState(BaseState):
|
|
26
|
+
chat_history: List[ChatMessage] = Field(default_factory=list)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@pytest.mark.parametrize(
|
|
30
|
+
["message", "expected_content"],
|
|
31
|
+
[
|
|
32
|
+
pytest.param(
|
|
33
|
+
[StringChatMessageContent(value="Hello, world!")],
|
|
34
|
+
ArrayChatMessageContent(value=[StringChatMessageContent(value="Hello, world!")]),
|
|
35
|
+
id="text_string_content",
|
|
36
|
+
),
|
|
37
|
+
pytest.param(
|
|
38
|
+
[ImageChatMessageContent(value=VellumImage(src="https://example.com/image.jpg"))],
|
|
39
|
+
ArrayChatMessageContent(
|
|
40
|
+
value=[ImageChatMessageContent(value=VellumImage(src="https://example.com/image.jpg"))]
|
|
41
|
+
),
|
|
42
|
+
id="multimodal_image",
|
|
43
|
+
),
|
|
44
|
+
pytest.param(
|
|
45
|
+
[
|
|
46
|
+
StringChatMessageContent(value="Look at this image:"),
|
|
47
|
+
ImageChatMessageContent(value=VellumImage(src="https://example.com/image.jpg")),
|
|
48
|
+
],
|
|
49
|
+
ArrayChatMessageContent(
|
|
50
|
+
value=[
|
|
51
|
+
StringChatMessageContent(value="Look at this image:"),
|
|
52
|
+
ImageChatMessageContent(value=VellumImage(src="https://example.com/image.jpg")),
|
|
53
|
+
]
|
|
54
|
+
),
|
|
55
|
+
id="text_and_multimodal_array",
|
|
56
|
+
),
|
|
57
|
+
],
|
|
58
|
+
)
|
|
59
|
+
def test_chat_message_trigger__initiated(
|
|
60
|
+
message: List[ArrayChatMessageContentItem],
|
|
61
|
+
expected_content: ArrayChatMessageContent,
|
|
62
|
+
):
|
|
63
|
+
"""Tests that ChatMessageTrigger appends user message on workflow initiation."""
|
|
64
|
+
|
|
65
|
+
# GIVEN a ChatMessageTrigger with a message
|
|
66
|
+
trigger = ChatMessageTrigger(message=message)
|
|
67
|
+
|
|
68
|
+
# AND a state with chat_history
|
|
69
|
+
state = ChatState()
|
|
70
|
+
|
|
71
|
+
# WHEN the initiated lifecycle hook is called
|
|
72
|
+
trigger.__on_workflow_initiated__(state)
|
|
73
|
+
|
|
74
|
+
# THEN the user message is appended to chat_history
|
|
75
|
+
assert len(state.chat_history) == 1
|
|
76
|
+
assert state.chat_history[0].role == "USER"
|
|
77
|
+
assert state.chat_history[0].text is None
|
|
78
|
+
assert state.chat_history[0].content == expected_content
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def test_chat_message_trigger__state_without_chat_history():
|
|
82
|
+
"""Tests that ChatMessageTrigger handles state without chat_history gracefully."""
|
|
83
|
+
|
|
84
|
+
# GIVEN a ChatMessageTrigger with a message
|
|
85
|
+
trigger = ChatMessageTrigger(message=[StringChatMessageContent(value="Hello")])
|
|
86
|
+
|
|
87
|
+
# AND a state without chat_history attribute
|
|
88
|
+
state = BaseState()
|
|
89
|
+
|
|
90
|
+
# WHEN the initiated lifecycle hook is called
|
|
91
|
+
trigger.__on_workflow_initiated__(state)
|
|
92
|
+
|
|
93
|
+
# THEN no error is raised and state is unchanged
|
|
94
|
+
assert not hasattr(state, "chat_history")
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def test_chat_message_trigger__graph_syntax():
|
|
98
|
+
"""Tests that ChatMessageTrigger can be used in graph syntax."""
|
|
99
|
+
|
|
100
|
+
# GIVEN a ChatMessageTrigger and a node
|
|
101
|
+
class TestNode(BaseNode):
|
|
102
|
+
pass
|
|
103
|
+
|
|
104
|
+
# WHEN we use trigger >> node syntax
|
|
105
|
+
graph = ChatMessageTrigger >> TestNode
|
|
106
|
+
|
|
107
|
+
# THEN a graph is created with the trigger edge
|
|
108
|
+
assert graph is not None
|
|
109
|
+
assert len(list(graph.trigger_edges)) == 1
|
|
110
|
+
assert list(graph.trigger_edges)[0].trigger_class == ChatMessageTrigger
|
|
111
|
+
assert list(graph.trigger_edges)[0].to_node == TestNode
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def test_chat_message_trigger__converts_vellum_value_objects():
|
|
115
|
+
"""Tests that ChatMessageTrigger converts VellumValue objects to ChatMessageContent."""
|
|
116
|
+
|
|
117
|
+
# GIVEN a message as VellumValue objects (as received from codegen/API)
|
|
118
|
+
vellum_value_message = [
|
|
119
|
+
StringVellumValue(type="STRING", value="Hello, world!"),
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
# WHEN a ChatMessageTrigger is created with VellumValue objects
|
|
123
|
+
trigger = ChatMessageTrigger(message=vellum_value_message)
|
|
124
|
+
|
|
125
|
+
# THEN the message is converted to ChatMessageContent
|
|
126
|
+
assert len(trigger.message) == 1
|
|
127
|
+
assert isinstance(trigger.message[0], StringChatMessageContent)
|
|
128
|
+
assert trigger.message[0].value == "Hello, world!"
|
|
129
|
+
|
|
130
|
+
# AND the trigger works correctly with state
|
|
131
|
+
state = ChatState()
|
|
132
|
+
trigger.__on_workflow_initiated__(state)
|
|
133
|
+
|
|
134
|
+
assert len(state.chat_history) == 1
|
|
135
|
+
assert state.chat_history[0].role == "USER"
|
|
136
|
+
assert state.chat_history[0].content == ArrayChatMessageContent(
|
|
137
|
+
value=[StringChatMessageContent(value="Hello, world!")]
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def test_chat_message_trigger__converts_dict_format():
|
|
142
|
+
"""Tests that ChatMessageTrigger converts dict format to ChatMessageContent."""
|
|
143
|
+
|
|
144
|
+
# GIVEN a message as dict objects (alternative API format)
|
|
145
|
+
dict_message = [
|
|
146
|
+
{"type": "STRING", "value": "Hello from dict!"},
|
|
147
|
+
]
|
|
148
|
+
|
|
149
|
+
# WHEN a ChatMessageTrigger is created with dict objects
|
|
150
|
+
trigger = ChatMessageTrigger(message=dict_message)
|
|
151
|
+
|
|
152
|
+
# THEN the message is converted to ChatMessageContent
|
|
153
|
+
assert len(trigger.message) == 1
|
|
154
|
+
assert isinstance(trigger.message[0], StringChatMessageContent)
|
|
155
|
+
assert trigger.message[0].value == "Hello from dict!"
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def test_chat_message_trigger__converts_string_message():
|
|
159
|
+
"""Tests that ChatMessageTrigger converts string messages to ChatMessageContent list."""
|
|
160
|
+
|
|
161
|
+
# GIVEN a message as a string
|
|
162
|
+
string_message = "Hello, world!"
|
|
163
|
+
|
|
164
|
+
# WHEN a ChatMessageTrigger is created with a string message
|
|
165
|
+
trigger = ChatMessageTrigger(message=string_message)
|
|
166
|
+
|
|
167
|
+
# THEN the message is converted to a list with a single StringChatMessageContent
|
|
168
|
+
assert len(trigger.message) == 1
|
|
169
|
+
assert isinstance(trigger.message[0], StringChatMessageContent)
|
|
170
|
+
assert trigger.message[0].value == "Hello, world!"
|
|
171
|
+
|
|
172
|
+
# AND the trigger works correctly with state
|
|
173
|
+
state = ChatState()
|
|
174
|
+
trigger.__on_workflow_initiated__(state)
|
|
175
|
+
|
|
176
|
+
assert len(state.chat_history) == 1
|
|
177
|
+
assert state.chat_history[0].role == "USER"
|
|
178
|
+
assert state.chat_history[0].content == ArrayChatMessageContent(
|
|
179
|
+
value=[StringChatMessageContent(value="Hello, world!")]
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def test_chat_message_trigger__raw_string_array__workflow_stream():
|
|
184
|
+
"""Tests that workflow.stream() works with raw string array after deserialize_trigger."""
|
|
185
|
+
|
|
186
|
+
# GIVEN a workflow with ChatMessageTrigger
|
|
187
|
+
class TestNode(BaseNode):
|
|
188
|
+
class Outputs(BaseOutputs):
|
|
189
|
+
result: str
|
|
190
|
+
|
|
191
|
+
def run(self) -> Outputs:
|
|
192
|
+
return self.Outputs(result="success")
|
|
193
|
+
|
|
194
|
+
class TestWorkflow(BaseWorkflow):
|
|
195
|
+
graph = ChatMessageTrigger >> TestNode
|
|
196
|
+
|
|
197
|
+
# AND a raw string array input (not wrapped in VellumValue format)
|
|
198
|
+
raw_string_array_input = {"message": ["Hello", "World"]}
|
|
199
|
+
|
|
200
|
+
# WHEN we deserialize the trigger with raw string array
|
|
201
|
+
trigger = TestWorkflow.deserialize_trigger(
|
|
202
|
+
trigger_id=ChatMessageTrigger.__id__,
|
|
203
|
+
inputs=raw_string_array_input,
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
# THEN the trigger is properly deserialized
|
|
207
|
+
assert isinstance(trigger, ChatMessageTrigger)
|
|
208
|
+
assert len(trigger.message) == 2
|
|
209
|
+
assert isinstance(trigger.message[0], StringChatMessageContent)
|
|
210
|
+
assert trigger.message[0].value == "Hello"
|
|
211
|
+
assert isinstance(trigger.message[1], StringChatMessageContent)
|
|
212
|
+
assert trigger.message[1].value == "World"
|
|
213
|
+
|
|
214
|
+
# AND the workflow can be streamed successfully
|
|
215
|
+
workflow = TestWorkflow()
|
|
216
|
+
events = list(workflow.stream(trigger=trigger))
|
|
217
|
+
|
|
218
|
+
# THEN the workflow completes successfully
|
|
219
|
+
assert len(events) > 0
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def test_chat_message_trigger__chat_history_defaulted_to_none():
|
|
223
|
+
"""Tests that workflow runs successfully when chat_history is defaulted to None."""
|
|
224
|
+
|
|
225
|
+
# GIVEN a state with chat_history defaulted to None
|
|
226
|
+
class NullableChatHistoryState(BaseState):
|
|
227
|
+
chat_history: Optional[List[ChatMessage]] = None
|
|
228
|
+
|
|
229
|
+
# AND a simple node
|
|
230
|
+
class TestNode(BaseNode):
|
|
231
|
+
class Outputs(BaseOutputs):
|
|
232
|
+
result: str
|
|
233
|
+
|
|
234
|
+
def run(self) -> Outputs:
|
|
235
|
+
return self.Outputs(result="success")
|
|
236
|
+
|
|
237
|
+
# AND a workflow with ChatMessageTrigger and the nullable chat_history state
|
|
238
|
+
class TestWorkflow(BaseWorkflow[BaseInputs, NullableChatHistoryState]):
|
|
239
|
+
graph = ChatMessageTrigger >> TestNode
|
|
240
|
+
|
|
241
|
+
# WHEN we run the workflow with a trigger
|
|
242
|
+
trigger = ChatMessageTrigger(message="Hello")
|
|
243
|
+
workflow = TestWorkflow()
|
|
244
|
+
terminal_event = workflow.run(trigger=trigger)
|
|
245
|
+
|
|
246
|
+
# THEN the workflow completes successfully
|
|
247
|
+
assert terminal_event.name == "workflow.execution.fulfilled"
|
|
248
|
+
|
|
249
|
+
# AND the final state has a contentful chat_history
|
|
250
|
+
final_state = terminal_event.final_state
|
|
251
|
+
assert final_state is not None
|
|
252
|
+
assert final_state.chat_history is not None
|
|
253
|
+
assert len(final_state.chat_history) == 1
|
|
254
|
+
assert final_state.chat_history[0].role == "USER"
|
|
255
|
+
assert final_state.chat_history[0].content == ArrayChatMessageContent(
|
|
256
|
+
value=[StringChatMessageContent(value="Hello")]
|
|
257
|
+
)
|
vellum/workflows/types/core.py
CHANGED
|
@@ -4,6 +4,7 @@ from threading import Event as ThreadingEvent
|
|
|
4
4
|
from typing import ( # type: ignore[attr-defined]
|
|
5
5
|
Any,
|
|
6
6
|
Dict,
|
|
7
|
+
Iterable,
|
|
7
8
|
List,
|
|
8
9
|
Union,
|
|
9
10
|
_GenericAlias,
|
|
@@ -17,6 +18,23 @@ JsonArray = List["Json"]
|
|
|
17
18
|
JsonObject = Dict[str, "Json"]
|
|
18
19
|
Json = Union[None, bool, int, float, str, JsonArray, JsonObject]
|
|
19
20
|
|
|
21
|
+
|
|
22
|
+
def is_json_type(types: Iterable) -> bool:
|
|
23
|
+
# Check explicitly for our internal JSON type.
|
|
24
|
+
# Matches the type found at vellum.workflows.types.core.Json
|
|
25
|
+
actual_types_with_explicit_ref = [
|
|
26
|
+
bool,
|
|
27
|
+
int,
|
|
28
|
+
float,
|
|
29
|
+
str,
|
|
30
|
+
List[Json],
|
|
31
|
+
Dict[str, Json],
|
|
32
|
+
]
|
|
33
|
+
with_none = [type(None), *actual_types_with_explicit_ref]
|
|
34
|
+
types_list = list(types)
|
|
35
|
+
return types_list == actual_types_with_explicit_ref or types_list == with_none
|
|
36
|
+
|
|
37
|
+
|
|
20
38
|
CancelSignal = Union[ThreadingEvent, MultiprocessingEvent]
|
|
21
39
|
|
|
22
40
|
# Unions and Generics inherit from `_GenericAlias` instead of `type`
|
|
@@ -181,8 +181,11 @@ class VellumIntegrationToolDefinition(UniversalBaseModel):
|
|
|
181
181
|
integration_name: str # "GITHUB", "SLACK", etc.
|
|
182
182
|
name: str # Specific action like "GITHUB_CREATE_AN_ISSUE"
|
|
183
183
|
|
|
184
|
-
#
|
|
185
|
-
description: str
|
|
184
|
+
# Optional description for tool base consistency
|
|
185
|
+
description: str = ""
|
|
186
|
+
|
|
187
|
+
# Optional toolkit version for pinning
|
|
188
|
+
toolkit_version: Optional[str] = None
|
|
186
189
|
|
|
187
190
|
|
|
188
191
|
class VellumIntegrationToolDetails(VellumIntegrationToolDefinition):
|
|
@@ -208,16 +211,6 @@ class MCPServer(UniversalBaseModel):
|
|
|
208
211
|
|
|
209
212
|
model_config = {"arbitrary_types_allowed": True}
|
|
210
213
|
|
|
211
|
-
def __setattr__(self, name: str, value: Any) -> None:
|
|
212
|
-
"""Override to automatically set serialization flags for environment variables."""
|
|
213
|
-
super().__setattr__(name, value)
|
|
214
|
-
|
|
215
|
-
if name == "bearer_token_value" and isinstance(value, EnvironmentVariableReference):
|
|
216
|
-
value.serialize_as_constant = True
|
|
217
|
-
|
|
218
|
-
if name == "api_key_header_value" and isinstance(value, EnvironmentVariableReference):
|
|
219
|
-
value.serialize_as_constant = True
|
|
220
|
-
|
|
221
214
|
|
|
222
215
|
class MCPToolDefinition(UniversalBaseModel):
|
|
223
216
|
name: str
|
|
@@ -234,4 +227,4 @@ ToolBase = Union[
|
|
|
234
227
|
ComposioToolDefinition,
|
|
235
228
|
VellumIntegrationToolDefinition,
|
|
236
229
|
]
|
|
237
|
-
Tool = Union[ToolBase, MCPServer]
|
|
230
|
+
Tool = Union[ToolBase, MCPServer, MCPToolDefinition]
|
|
@@ -6,6 +6,7 @@ if TYPE_CHECKING:
|
|
|
6
6
|
from vellum.workflows import BaseWorkflow
|
|
7
7
|
from vellum.workflows.inputs import BaseInputs
|
|
8
8
|
from vellum.workflows.nodes import BaseNode
|
|
9
|
+
from vellum.workflows.nodes.bases.base_adornment_node import BaseAdornmentNode
|
|
9
10
|
from vellum.workflows.outputs import BaseOutputs
|
|
10
11
|
from vellum.workflows.state import BaseState
|
|
11
12
|
|
|
@@ -37,6 +38,17 @@ def import_workflow_class() -> Type["BaseWorkflow"]:
|
|
|
37
38
|
return BaseWorkflow
|
|
38
39
|
|
|
39
40
|
|
|
41
|
+
@cache
|
|
42
|
+
def import_base_adornment_node() -> Type["BaseAdornmentNode"]:
|
|
43
|
+
"""
|
|
44
|
+
Helper function to help avoid circular imports.
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
from vellum.workflows.nodes.bases.base_adornment_node import BaseAdornmentNode
|
|
48
|
+
|
|
49
|
+
return BaseAdornmentNode
|
|
50
|
+
|
|
51
|
+
|
|
40
52
|
def is_node_class(obj: Any) -> TypeGuard[Type["BaseNode"]]:
|
|
41
53
|
base_node_class = _import_node_class()
|
|
42
54
|
return isinstance(obj, type) and issubclass(obj, base_node_class)
|
|
@@ -101,3 +101,15 @@ def test_infer_types(cls, attr_name, expected_type):
|
|
|
101
101
|
)
|
|
102
102
|
def test_class_attr_names(cls, expected_attr_names):
|
|
103
103
|
assert get_class_attr_names(cls) == expected_attr_names
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def test_infer_types__non_existent_attribute__raises_clear_error():
|
|
107
|
+
"""Test that infer_types raises a clear error message for non-existent attributes."""
|
|
108
|
+
|
|
109
|
+
# GIVEN a class with some attributes
|
|
110
|
+
# WHEN we try to infer types for a non-existent attribute
|
|
111
|
+
# THEN it should raise an AttributeError with a clear message
|
|
112
|
+
with pytest.raises(AttributeError) as exc_info:
|
|
113
|
+
infer_types(ExampleClass, "non_existent_attribute")
|
|
114
|
+
|
|
115
|
+
assert "'ExampleClass' has no attribute 'non_existent_attribute'" in str(exc_info.value)
|
vellum/workflows/types/utils.py
CHANGED
|
@@ -91,7 +91,10 @@ def infer_types(object_: Type, attr_name: str, localns: Optional[Dict[str, Any]]
|
|
|
91
91
|
if len(types_list) == len(parts):
|
|
92
92
|
return tuple(types_list)
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
try:
|
|
95
|
+
type_hints = get_type_hints(class_, localns=LOCAL_NS if localns is None else {**LOCAL_NS, **localns})
|
|
96
|
+
except AttributeError:
|
|
97
|
+
type_hints = {}
|
|
95
98
|
if attr_name in type_hints:
|
|
96
99
|
type_hint = type_hints[attr_name]
|
|
97
100
|
if get_origin(type_hint) is ClassVar:
|
|
@@ -121,12 +124,14 @@ def infer_types(object_: Type, attr_name: str, localns: Optional[Dict[str, Any]]
|
|
|
121
124
|
class_attribute = class_attributes[attr_name]
|
|
122
125
|
return resolve_types(class_attribute)
|
|
123
126
|
|
|
124
|
-
raise AttributeError(f"
|
|
127
|
+
raise AttributeError(f"'{object_.__name__}' has no attribute '{attr_name}'")
|
|
125
128
|
except TypeError:
|
|
126
129
|
# Python 3.13+: object class doesn't have __annotations__ by default
|
|
127
130
|
# Use getattr with default to safely access annotations
|
|
128
131
|
annotations = getattr(object_, "__annotations__", {})
|
|
129
132
|
annotation_value = annotations.get(attr_name, undefined)
|
|
133
|
+
if annotation_value is undefined:
|
|
134
|
+
raise AttributeError(f"'{object_.__name__}' has no attribute '{attr_name}'")
|
|
130
135
|
raise AttributeError(
|
|
131
136
|
f"Found 3.9+ typing syntax for field '{attr_name}' on class '{object_.__name__}' – {annotation_value}. Type annotations must be compatible with python version 3.8. " # noqa: E501
|
|
132
137
|
)
|
|
@@ -219,3 +224,28 @@ def get_original_base(cls: Type) -> Type:
|
|
|
219
224
|
# in Python 3.12, there is `from types import get_original_bases`, making this future proof
|
|
220
225
|
# https://docs.python.org/3/library/types.html#types.get_original_bases
|
|
221
226
|
return cls.__orig_bases__[0] # type: ignore[attr-defined]
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def coerce_to_declared_type(value: Any, declared_type: Type, field_name: str) -> Any:
|
|
230
|
+
"""Coerce a value to the declared type if needed.
|
|
231
|
+
|
|
232
|
+
This handles cases where the API returns a float for an int field
|
|
233
|
+
(since NumberVellumValue.value is typed as float).
|
|
234
|
+
|
|
235
|
+
Args:
|
|
236
|
+
value: The value to coerce
|
|
237
|
+
declared_type: The expected type from the field annotation
|
|
238
|
+
field_name: The name of the field (for error messages)
|
|
239
|
+
|
|
240
|
+
Returns:
|
|
241
|
+
The coerced value
|
|
242
|
+
|
|
243
|
+
Raises:
|
|
244
|
+
ValueError: If the value cannot be safely coerced to the declared type
|
|
245
|
+
"""
|
|
246
|
+
if declared_type is int and isinstance(value, float):
|
|
247
|
+
if value.is_integer():
|
|
248
|
+
return int(value)
|
|
249
|
+
raise ValueError(f"Expected integer for input '{field_name}', but received non-integer float: {value}")
|
|
250
|
+
|
|
251
|
+
return value
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""Pydantic models for workflow metadata.json files.
|
|
2
|
+
|
|
3
|
+
The metadata.json file is generated alongside workflow code to ensure stable,
|
|
4
|
+
UI-aligned identifiers without relying on Python display classes. It contains
|
|
5
|
+
mappings between code paths and UI identifiers for nodes, triggers, edges, and
|
|
6
|
+
dataset rows.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Dict, Optional
|
|
10
|
+
|
|
11
|
+
from vellum.client.core.pydantic_utilities import UniversalBaseModel
|
|
12
|
+
from vellum.client.types.code_resource_definition import CodeResourceDefinition
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class RunnerConfig(UniversalBaseModel):
|
|
16
|
+
"""Configuration for the workflow runner environment.
|
|
17
|
+
|
|
18
|
+
This specifies the container image and version information used to execute
|
|
19
|
+
the workflow.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
container_image_name: Optional[str] = None
|
|
23
|
+
"""The name of the container image to use. If not provided, defaults to the
|
|
24
|
+
standard Python workflow runtime image."""
|
|
25
|
+
|
|
26
|
+
container_image_tag: Optional[str] = None
|
|
27
|
+
"""The tag of the container image to use. If not provided, defaults to the
|
|
28
|
+
latest tag."""
|
|
29
|
+
|
|
30
|
+
codegen_version: Optional[str] = None
|
|
31
|
+
"""The version of codegen used to generate the workflow artifact.
|
|
32
|
+
|
|
33
|
+
.. deprecated::
|
|
34
|
+
This field is deprecated. Use `sdk_version` instead.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
sdk_version: Optional[str] = None
|
|
38
|
+
"""The SDK version the workflow is intended to run on."""
|
|
39
|
+
|
|
40
|
+
is_deployment_inlining_enabled: bool = False
|
|
41
|
+
"""Whether deployment inlining is enabled for this workflow."""
|
|
42
|
+
|
|
43
|
+
server_version: Optional[str] = None
|
|
44
|
+
"""The server version the workflow is intended to run on. This gets set when
|
|
45
|
+
deploying a workflow with a hotswappable custom image."""
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class WorkflowMetadata(UniversalBaseModel):
|
|
49
|
+
"""Metadata persisted alongside generated workflow code.
|
|
50
|
+
|
|
51
|
+
This metadata ensures stable, UI-aligned identifiers without relying on
|
|
52
|
+
Python display classes. It is generated by the codegen system and consumed
|
|
53
|
+
during workflow serialization to maintain consistent IDs across round-trips.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
runner_config: Optional[RunnerConfig] = None
|
|
57
|
+
"""Configuration for the workflow runner environment."""
|
|
58
|
+
|
|
59
|
+
label: Optional[str] = None
|
|
60
|
+
"""Human-readable label for the workflow."""
|
|
61
|
+
|
|
62
|
+
codegen_version: Optional[str] = None
|
|
63
|
+
"""The version of codegen used to generate this workflow.
|
|
64
|
+
|
|
65
|
+
.. deprecated::
|
|
66
|
+
This field is deprecated. Use `runner_config.codegen_version` instead.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
server_version: Optional[str] = None
|
|
70
|
+
"""The server version this workflow was generated for.
|
|
71
|
+
|
|
72
|
+
.. deprecated::
|
|
73
|
+
This field is deprecated. Use `runner_config.server_version` instead.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
node_id_to_file_mapping: Dict[str, CodeResourceDefinition] = {}
|
|
77
|
+
"""Mapping of node IDs to their code resource definitions.
|
|
78
|
+
|
|
79
|
+
Key: Node UUID string
|
|
80
|
+
Value: CodeResourceDefinition containing the module path and class name
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
trigger_path_to_id_mapping: Dict[str, str] = {}
|
|
84
|
+
"""Mapping of trigger class paths to their UI trigger IDs.
|
|
85
|
+
|
|
86
|
+
Key: ".<relative_trigger_module_path>.<TriggerClassName>"
|
|
87
|
+
Value: UI trigger ID (UUID string)
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
trigger_attribute_id_mapping: Dict[str, str] = {}
|
|
91
|
+
"""Mapping of trigger attribute keys to their UI attribute IDs.
|
|
92
|
+
|
|
93
|
+
Key: "<trigger_path>|<attribute_key>"
|
|
94
|
+
Value: Attribute ID (UUID string)
|
|
95
|
+
|
|
96
|
+
This ensures trigger attribute IDs remain stable across serialization
|
|
97
|
+
round-trips.
|
|
98
|
+
"""
|
|
99
|
+
|
|
100
|
+
entrypoint: Optional[str] = None
|
|
101
|
+
"""The UI entrypoint node ID.
|
|
102
|
+
|
|
103
|
+
Kept for compatibility. Edge IDs for entrypoint flows are now included in
|
|
104
|
+
edges_to_id_mapping using the manual trigger path as the source.
|
|
105
|
+
"""
|
|
106
|
+
|
|
107
|
+
edges_to_id_mapping: Dict[str, str] = {}
|
|
108
|
+
"""Mapping of edge path keys to their UI edge IDs.
|
|
109
|
+
|
|
110
|
+
Key: "<source_path>|<target_node_path>"
|
|
111
|
+
where:
|
|
112
|
+
source_path := "<trigger_module_path>.<TriggerClassName>" for trigger edges
|
|
113
|
+
or "<module_path>.<NodeClassName>.Ports.<source_handle_id>"
|
|
114
|
+
for node->node edges (handle id disambiguates multiple edges)
|
|
115
|
+
target_node_path := "<module_path>.<ClassName>.Trigger" for the target node
|
|
116
|
+
Value: UI edge ID (UUID string)
|
|
117
|
+
"""
|
|
118
|
+
|
|
119
|
+
dataset_row_index_to_id_mapping: Dict[str, str] = {}
|
|
120
|
+
"""Mapping of dataset row indices to their UI row IDs.
|
|
121
|
+
|
|
122
|
+
Key: Dataset row index (0-based) as a string
|
|
123
|
+
Value: UI dataset row ID (UUID string)
|
|
124
|
+
"""
|