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
|
@@ -29,6 +29,7 @@ from typing import (
|
|
|
29
29
|
|
|
30
30
|
from pydantic import ValidationError
|
|
31
31
|
|
|
32
|
+
from vellum.utils.uuid import is_valid_uuid
|
|
32
33
|
from vellum.workflows.edges import Edge
|
|
33
34
|
from vellum.workflows.emitters.base import BaseWorkflowEmitter
|
|
34
35
|
from vellum.workflows.errors import WorkflowError, WorkflowErrorCode
|
|
@@ -38,6 +39,8 @@ from vellum.workflows.events.node import (
|
|
|
38
39
|
NodeExecutionFulfilledEvent,
|
|
39
40
|
NodeExecutionInitiatedBody,
|
|
40
41
|
NodeExecutionInitiatedEvent,
|
|
42
|
+
NodeExecutionLogBody,
|
|
43
|
+
NodeExecutionLogEvent,
|
|
41
44
|
NodeExecutionPausedBody,
|
|
42
45
|
NodeExecutionPausedEvent,
|
|
43
46
|
NodeExecutionRejectedBody,
|
|
@@ -74,6 +77,7 @@ from vellum.workflows.nodes.bases import BaseNode
|
|
|
74
77
|
from vellum.workflows.nodes.mocks import MockNodeExecutionArg
|
|
75
78
|
from vellum.workflows.nodes.utils import get_unadorned_node
|
|
76
79
|
from vellum.workflows.outputs import BaseOutputs
|
|
80
|
+
from vellum.workflows.references.trigger import TriggerAttributeReference
|
|
77
81
|
from vellum.workflows.resolvers.base import BaseWorkflowResolver
|
|
78
82
|
from vellum.workflows.runner import WorkflowRunner
|
|
79
83
|
from vellum.workflows.runner.runner import ExternalInputsArg, RunFromNodeArg
|
|
@@ -271,8 +275,6 @@ class BaseWorkflow(Generic[InputsType, StateType], BaseExecutable, metaclass=_Ba
|
|
|
271
275
|
for resolver in self.resolvers:
|
|
272
276
|
resolver.register_workflow_instance(self)
|
|
273
277
|
|
|
274
|
-
self.validate()
|
|
275
|
-
|
|
276
278
|
@property
|
|
277
279
|
def context(self) -> WorkflowContext:
|
|
278
280
|
return self._context
|
|
@@ -289,12 +291,12 @@ class BaseWorkflow(Generic[InputsType, StateType], BaseExecutable, metaclass=_Ba
|
|
|
289
291
|
for item in graph:
|
|
290
292
|
if isinstance(item, Graph):
|
|
291
293
|
graphs.append(item)
|
|
292
|
-
elif issubclass(item, BaseNode):
|
|
294
|
+
elif inspect.isclass(item) and issubclass(item, BaseNode):
|
|
293
295
|
graphs.append(Graph.from_node(item))
|
|
294
296
|
else:
|
|
295
297
|
raise ValueError(f"Unexpected graph type: {type(item)}")
|
|
296
298
|
return graphs
|
|
297
|
-
if issubclass(graph, BaseNode):
|
|
299
|
+
if inspect.isclass(graph) and issubclass(graph, BaseNode):
|
|
298
300
|
return [Graph.from_node(graph)]
|
|
299
301
|
raise ValueError(f"Unexpected graph type: {type(graph)}")
|
|
300
302
|
|
|
@@ -526,6 +528,7 @@ class BaseWorkflow(Generic[InputsType, StateType], BaseExecutable, metaclass=_Ba
|
|
|
526
528
|
max_concurrency: Optional[int] = None,
|
|
527
529
|
timeout: Optional[float] = None,
|
|
528
530
|
trigger: Optional[BaseTrigger] = None,
|
|
531
|
+
event_max_size: Optional[int] = None,
|
|
529
532
|
) -> WorkflowEventStream:
|
|
530
533
|
"""
|
|
531
534
|
Invoke a Workflow, yielding events as they are emitted.
|
|
@@ -576,6 +579,10 @@ class BaseWorkflow(Generic[InputsType, StateType], BaseExecutable, metaclass=_Ba
|
|
|
576
579
|
The trigger instance is bound to the workflow state, making its attributes accessible to downstream nodes.
|
|
577
580
|
Required for workflows that only have IntegrationTrigger; optional for workflows with both ManualTrigger
|
|
578
581
|
and IntegrationTrigger.
|
|
582
|
+
|
|
583
|
+
event_max_size: Optional[int] = None
|
|
584
|
+
The maximum size in bytes for serialized events. If an event's serialized size exceeds this value,
|
|
585
|
+
the outputs will be set to an empty dict.
|
|
579
586
|
"""
|
|
580
587
|
|
|
581
588
|
should_yield = event_filter or workflow_event_filter
|
|
@@ -593,6 +600,7 @@ class BaseWorkflow(Generic[InputsType, StateType], BaseExecutable, metaclass=_Ba
|
|
|
593
600
|
init_execution_context=self._execution_context,
|
|
594
601
|
trigger=trigger,
|
|
595
602
|
execution_id=execution_id,
|
|
603
|
+
event_max_size=event_max_size,
|
|
596
604
|
)
|
|
597
605
|
self._current_runner = runner
|
|
598
606
|
runner_stream = runner.stream()
|
|
@@ -604,15 +612,28 @@ class BaseWorkflow(Generic[InputsType, StateType], BaseExecutable, metaclass=_Ba
|
|
|
604
612
|
|
|
605
613
|
return WorkflowEventGenerator(_generate_filtered_events(), runner_stream.span_id)
|
|
606
614
|
|
|
607
|
-
|
|
615
|
+
@classmethod
|
|
616
|
+
def validate(cls) -> None:
|
|
608
617
|
"""
|
|
609
618
|
Validates the Workflow, by running through our list of linter rules.
|
|
610
619
|
"""
|
|
611
|
-
# TODO: Implement rule that all entrypoints are non empty
|
|
612
|
-
# https://app.shortcut.com/vellum/story/4327
|
|
613
|
-
pass
|
|
614
620
|
|
|
615
|
-
|
|
621
|
+
cls._validate_no_self_edges()
|
|
622
|
+
|
|
623
|
+
@classmethod
|
|
624
|
+
def get_all_nodes_recursive(cls) -> Iterator[Type[BaseNode]]:
|
|
625
|
+
"""
|
|
626
|
+
Returns an iterator over all nodes in the Workflow, including nodes nested in subworkflows.
|
|
627
|
+
"""
|
|
628
|
+
for node in cls.get_all_nodes():
|
|
629
|
+
yield node
|
|
630
|
+
for node_ref in node:
|
|
631
|
+
attr_value = node_ref.instance
|
|
632
|
+
if inspect.isclass(attr_value) and issubclass(attr_value, BaseWorkflow):
|
|
633
|
+
yield from attr_value.get_all_nodes_recursive()
|
|
634
|
+
|
|
635
|
+
@classmethod
|
|
636
|
+
def resolve_node_ref(cls, node_ref: Union[Type[BaseNode], UUID, str]) -> Type[BaseNode]:
|
|
616
637
|
"""
|
|
617
638
|
Resolve a node reference (class, UUID, or string) to a node class.
|
|
618
639
|
|
|
@@ -630,18 +651,27 @@ class BaseWorkflow(Generic[InputsType, StateType], BaseExecutable, metaclass=_Ba
|
|
|
630
651
|
return node_ref
|
|
631
652
|
|
|
632
653
|
candidate_nodes: List[Type[BaseNode]] = []
|
|
633
|
-
for node in
|
|
654
|
+
for node in cls.get_all_nodes_recursive():
|
|
634
655
|
candidate_nodes.append(node)
|
|
635
656
|
wrapped_node = get_unadorned_node(node)
|
|
636
657
|
if wrapped_node != node:
|
|
637
658
|
candidate_nodes.append(wrapped_node)
|
|
638
659
|
|
|
639
660
|
if isinstance(node_ref, UUID):
|
|
661
|
+
node_uuid = node_ref
|
|
662
|
+
elif is_valid_uuid(node_ref):
|
|
663
|
+
node_uuid = UUID(node_ref)
|
|
664
|
+
else:
|
|
665
|
+
node_uuid = None
|
|
666
|
+
|
|
667
|
+
if node_uuid:
|
|
640
668
|
for node in candidate_nodes:
|
|
641
|
-
if node.__id__ ==
|
|
669
|
+
if node.__id__ == node_uuid:
|
|
642
670
|
return node
|
|
643
|
-
|
|
644
|
-
|
|
671
|
+
raise WorkflowInitializationException(
|
|
672
|
+
message=f"Node '{node_uuid}' not found in workflow",
|
|
673
|
+
raw_data={"node_ref": str(node_uuid)},
|
|
674
|
+
)
|
|
645
675
|
|
|
646
676
|
if isinstance(node_ref, str):
|
|
647
677
|
try:
|
|
@@ -650,14 +680,23 @@ class BaseWorkflow(Generic[InputsType, StateType], BaseExecutable, metaclass=_Ba
|
|
|
650
680
|
node_class = getattr(module, class_name)
|
|
651
681
|
if inspect.isclass(node_class) and issubclass(node_class, BaseNode):
|
|
652
682
|
return node_class
|
|
653
|
-
raise WorkflowInitializationException(
|
|
683
|
+
raise WorkflowInitializationException(
|
|
684
|
+
message=f"Node '{node_ref}' not found in workflow",
|
|
685
|
+
raw_data={"node_ref": node_ref},
|
|
686
|
+
)
|
|
654
687
|
except (ValueError, ModuleNotFoundError, AttributeError):
|
|
655
688
|
for node in candidate_nodes:
|
|
656
689
|
if f"{node.__module__}.{node.__name__}" == node_ref:
|
|
657
690
|
return node
|
|
658
|
-
raise WorkflowInitializationException(
|
|
691
|
+
raise WorkflowInitializationException(
|
|
692
|
+
message=f"Node '{node_ref}' not found in workflow",
|
|
693
|
+
raw_data={"node_ref": node_ref},
|
|
694
|
+
)
|
|
659
695
|
|
|
660
|
-
raise WorkflowInitializationException(
|
|
696
|
+
raise WorkflowInitializationException(
|
|
697
|
+
message=f"Node '{node_ref}' not found in workflow",
|
|
698
|
+
raw_data={"node_ref": str(node_ref)},
|
|
699
|
+
)
|
|
661
700
|
|
|
662
701
|
def run_node(
|
|
663
702
|
self, node: Union[Type[BaseNode], UUID, str], *, inputs: Optional[Dict[str, Any]] = None
|
|
@@ -676,7 +715,7 @@ class BaseWorkflow(Generic[InputsType, StateType], BaseExecutable, metaclass=_Ba
|
|
|
676
715
|
Raises:
|
|
677
716
|
ValueError: If the node reference cannot be resolved
|
|
678
717
|
"""
|
|
679
|
-
resolved_node = self.
|
|
718
|
+
resolved_node = self.resolve_node_ref(node)
|
|
680
719
|
runner = WorkflowRunner(self)
|
|
681
720
|
span_id = uuid4()
|
|
682
721
|
node_instance = resolved_node(state=self.get_default_state(), context=self._context, inputs=inputs)
|
|
@@ -717,12 +756,27 @@ class BaseWorkflow(Generic[InputsType, StateType], BaseExecutable, metaclass=_Ba
|
|
|
717
756
|
return self.get_inputs_class()()
|
|
718
757
|
|
|
719
758
|
def get_default_state(
|
|
720
|
-
self,
|
|
759
|
+
self,
|
|
760
|
+
workflow_inputs: Optional[InputsType] = None,
|
|
761
|
+
execution_id: Optional[UUID] = None,
|
|
762
|
+
*,
|
|
763
|
+
trigger_attributes: Optional[Dict[TriggerAttributeReference, Any]] = None,
|
|
721
764
|
) -> StateType:
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
765
|
+
resolved_inputs: Optional[InputsType] = workflow_inputs
|
|
766
|
+
|
|
767
|
+
meta_payload: Dict[str, Any] = {
|
|
768
|
+
"parent": self._parent_state,
|
|
769
|
+
"workflow_definition": self.__class__,
|
|
770
|
+
"workflow_inputs": resolved_inputs,
|
|
771
|
+
}
|
|
772
|
+
if trigger_attributes is not None:
|
|
773
|
+
meta_payload["trigger_attributes"] = trigger_attributes
|
|
774
|
+
|
|
775
|
+
meta = StateMeta.model_validate(
|
|
776
|
+
meta_payload,
|
|
777
|
+
context={
|
|
778
|
+
"workflow_definition": self.__class__,
|
|
779
|
+
},
|
|
726
780
|
)
|
|
727
781
|
|
|
728
782
|
# Makes the uuid factory mocker work this way instead of setting in cosntructor
|
|
@@ -781,11 +835,13 @@ class BaseWorkflow(Generic[InputsType, StateType], BaseExecutable, metaclass=_Ba
|
|
|
781
835
|
|
|
782
836
|
state_class = cls.get_state_class()
|
|
783
837
|
if "meta" in state:
|
|
838
|
+
meta_payload = dict(state["meta"])
|
|
839
|
+
if workflow_inputs is not None:
|
|
840
|
+
meta_payload["workflow_inputs"] = workflow_inputs
|
|
841
|
+
meta_payload.setdefault("workflow_definition", cls)
|
|
842
|
+
|
|
784
843
|
state["meta"] = StateMeta.model_validate(
|
|
785
|
-
|
|
786
|
-
**state["meta"],
|
|
787
|
-
"workflow_inputs": workflow_inputs,
|
|
788
|
-
},
|
|
844
|
+
meta_payload,
|
|
789
845
|
context={
|
|
790
846
|
"workflow_definition": cls,
|
|
791
847
|
},
|
|
@@ -794,7 +850,9 @@ class BaseWorkflow(Generic[InputsType, StateType], BaseExecutable, metaclass=_Ba
|
|
|
794
850
|
return state_class(**state)
|
|
795
851
|
|
|
796
852
|
@classmethod
|
|
797
|
-
def deserialize_trigger(
|
|
853
|
+
def deserialize_trigger(
|
|
854
|
+
cls, trigger_id: Optional[Union[str, UUID]], inputs: dict
|
|
855
|
+
) -> Union[InputsType, BaseTrigger]:
|
|
798
856
|
"""
|
|
799
857
|
Deserialize a trigger from a trigger_id and inputs dict.
|
|
800
858
|
|
|
@@ -803,8 +861,12 @@ class BaseWorkflow(Generic[InputsType, StateType], BaseExecutable, metaclass=_Ba
|
|
|
803
861
|
|
|
804
862
|
Parameters
|
|
805
863
|
----------
|
|
806
|
-
trigger_id: Optional[UUID]
|
|
807
|
-
The
|
|
864
|
+
trigger_id: Optional[Union[str, UUID]]
|
|
865
|
+
The identifier of the trigger class to instantiate. Can be:
|
|
866
|
+
- None: Returns workflow Inputs
|
|
867
|
+
- UUID: Matches by trigger class __id__
|
|
868
|
+
- str (valid UUID): Matches by trigger class __id__
|
|
869
|
+
- str (non-UUID): Matches by trigger name (from __trigger_name__)
|
|
808
870
|
|
|
809
871
|
inputs: dict
|
|
810
872
|
The inputs to pass to the trigger or Inputs constructor.
|
|
@@ -824,18 +886,54 @@ class BaseWorkflow(Generic[InputsType, StateType], BaseExecutable, metaclass=_Ba
|
|
|
824
886
|
inputs_class = cls.get_inputs_class()
|
|
825
887
|
return inputs_class(**inputs)
|
|
826
888
|
|
|
889
|
+
# Determine if trigger_id is a UUID or a name string
|
|
890
|
+
resolved_trigger_id: Optional[UUID] = None
|
|
891
|
+
trigger_name: Optional[str] = None
|
|
892
|
+
|
|
893
|
+
if isinstance(trigger_id, UUID):
|
|
894
|
+
resolved_trigger_id = trigger_id
|
|
895
|
+
elif is_valid_uuid(trigger_id):
|
|
896
|
+
resolved_trigger_id = UUID(trigger_id)
|
|
897
|
+
else:
|
|
898
|
+
trigger_name = trigger_id
|
|
899
|
+
|
|
827
900
|
trigger_classes = []
|
|
828
901
|
for subgraph in cls.get_subgraphs():
|
|
829
902
|
for trigger_class in subgraph.triggers:
|
|
830
|
-
|
|
831
|
-
|
|
903
|
+
# Match by UUID
|
|
904
|
+
if resolved_trigger_id is not None and trigger_class.__id__ == resolved_trigger_id:
|
|
905
|
+
try:
|
|
906
|
+
return trigger_class(**inputs)
|
|
907
|
+
except Exception as e:
|
|
908
|
+
raise WorkflowInitializationException(
|
|
909
|
+
message=f"Failed to instantiate trigger {trigger_class.__name__}: {e}",
|
|
910
|
+
workflow_definition=cls,
|
|
911
|
+
) from e
|
|
912
|
+
|
|
913
|
+
# Match by name
|
|
914
|
+
if trigger_name is not None and trigger_class.__trigger_name__ == trigger_name:
|
|
915
|
+
try:
|
|
916
|
+
return trigger_class(**inputs)
|
|
917
|
+
except Exception as e:
|
|
918
|
+
raise WorkflowInitializationException(
|
|
919
|
+
message=f"Failed to instantiate trigger {trigger_class.__name__}: {e}",
|
|
920
|
+
workflow_definition=cls,
|
|
921
|
+
) from e
|
|
832
922
|
|
|
833
923
|
trigger_classes.append(trigger_class)
|
|
834
924
|
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
925
|
+
# Build helpful error message
|
|
926
|
+
if trigger_name is not None:
|
|
927
|
+
available_names = [trigger_class.__trigger_name__ for trigger_class in trigger_classes]
|
|
928
|
+
raise WorkflowInitializationException(
|
|
929
|
+
message=f"No trigger class found with name '{trigger_name}' in workflow {cls.__name__}. "
|
|
930
|
+
f"Available trigger names: {available_names}"
|
|
931
|
+
)
|
|
932
|
+
else:
|
|
933
|
+
raise WorkflowInitializationException(
|
|
934
|
+
message=f"No trigger class found with id {trigger_id} in workflow {cls.__name__}. "
|
|
935
|
+
f"Available trigger classes: {[trigger_class.__name__ for trigger_class in trigger_classes]}"
|
|
936
|
+
)
|
|
839
937
|
|
|
840
938
|
@staticmethod
|
|
841
939
|
def load_from_module(module_path: str) -> Type["BaseWorkflow"]:
|
|
@@ -874,6 +972,19 @@ class BaseWorkflow(Generic[InputsType, StateType], BaseExecutable, metaclass=_Ba
|
|
|
874
972
|
raise WorkflowInitializationException(message=f"Invalid variable reference: {e}") from e
|
|
875
973
|
except Exception as e:
|
|
876
974
|
raise WorkflowInitializationException(message=f"Unexpected failure while loading module: {e}") from e
|
|
975
|
+
|
|
976
|
+
# Attempt to load optional display sidecar module to trigger node ID annotations
|
|
977
|
+
display_path = f"{module_path}.display"
|
|
978
|
+
try:
|
|
979
|
+
importlib.import_module(display_path)
|
|
980
|
+
except ModuleNotFoundError:
|
|
981
|
+
# No display package for this workflow; that's fine.
|
|
982
|
+
pass
|
|
983
|
+
except Exception as e:
|
|
984
|
+
raise WorkflowInitializationException(
|
|
985
|
+
message=f"Unexpected failure while loading display module '{display_path}': {e}"
|
|
986
|
+
) from e
|
|
987
|
+
|
|
877
988
|
workflows: List[Type[BaseWorkflow]] = []
|
|
878
989
|
for name in dir(module):
|
|
879
990
|
if name.startswith("__"):
|
|
@@ -905,6 +1016,35 @@ class BaseWorkflow(Generic[InputsType, StateType], BaseExecutable, metaclass=_Ba
|
|
|
905
1016
|
for emitter in self.emitters:
|
|
906
1017
|
emitter.join()
|
|
907
1018
|
|
|
1019
|
+
@classmethod
|
|
1020
|
+
def _validate_no_self_edges(cls) -> None:
|
|
1021
|
+
"""
|
|
1022
|
+
Validate that the workflow graph doesn't contain unconditional self-edges (infinite loops).
|
|
1023
|
+
|
|
1024
|
+
A node is considered to have an unconditional self-edge if all of its ports target itself.
|
|
1025
|
+
|
|
1026
|
+
Args:
|
|
1027
|
+
edges: List of edge dictionaries from the serialized workflow
|
|
1028
|
+
|
|
1029
|
+
Raises:
|
|
1030
|
+
WorkflowInitializationException: If an unconditional self-edge is detected
|
|
1031
|
+
"""
|
|
1032
|
+
|
|
1033
|
+
for node in cls.get_all_nodes():
|
|
1034
|
+
node_ports = [list(port.edges) for port in node.Ports]
|
|
1035
|
+
if (
|
|
1036
|
+
all(
|
|
1037
|
+
all(edge.to_node == node for edge in port_edges) and len(port_edges) > 0
|
|
1038
|
+
for port_edges in node_ports
|
|
1039
|
+
)
|
|
1040
|
+
and len(node_ports) > 0
|
|
1041
|
+
):
|
|
1042
|
+
raise WorkflowInitializationException(
|
|
1043
|
+
message=f"Graph contains a self-edge ({node.__name__} >> {node.__name__}).",
|
|
1044
|
+
workflow_definition=cls,
|
|
1045
|
+
code=WorkflowErrorCode.INVALID_WORKFLOW,
|
|
1046
|
+
)
|
|
1047
|
+
|
|
908
1048
|
|
|
909
1049
|
WorkflowExecutionInitiatedBody.model_rebuild()
|
|
910
1050
|
WorkflowExecutionFulfilledBody.model_rebuild()
|
|
@@ -920,6 +1060,7 @@ NodeExecutionRejectedBody.model_rebuild()
|
|
|
920
1060
|
NodeExecutionPausedBody.model_rebuild()
|
|
921
1061
|
NodeExecutionResumedBody.model_rebuild()
|
|
922
1062
|
NodeExecutionStreamingBody.model_rebuild()
|
|
1063
|
+
NodeExecutionLogBody.model_rebuild()
|
|
923
1064
|
|
|
924
1065
|
WorkflowExecutionInitiatedEvent.model_rebuild()
|
|
925
1066
|
WorkflowExecutionFulfilledEvent.model_rebuild()
|
|
@@ -935,5 +1076,6 @@ NodeExecutionRejectedEvent.model_rebuild()
|
|
|
935
1076
|
NodeExecutionPausedEvent.model_rebuild()
|
|
936
1077
|
NodeExecutionResumedEvent.model_rebuild()
|
|
937
1078
|
NodeExecutionStreamingEvent.model_rebuild()
|
|
1079
|
+
NodeExecutionLogEvent.model_rebuild()
|
|
938
1080
|
|
|
939
1081
|
StateMeta.model_rebuild()
|
|
@@ -340,6 +340,32 @@ def test_workflow__unsupported_graph_item():
|
|
|
340
340
|
assert "Unexpected graph type: <class 'int'>" in str(exc_info.value)
|
|
341
341
|
|
|
342
342
|
|
|
343
|
+
def test_resolve_graph__non_class_item_in_set():
|
|
344
|
+
"""Test that _resolve_graph properly handles non-class items in a set without crashing on issubclass()."""
|
|
345
|
+
# GIVEN a non-class value (a string, not a class)
|
|
346
|
+
# WHEN we call _resolve_graph with a set containing a non-class value
|
|
347
|
+
with pytest.raises(ValueError) as exc_info:
|
|
348
|
+
BaseWorkflow._resolve_graph({"not_a_class"}) # type: ignore
|
|
349
|
+
|
|
350
|
+
# THEN it should raise ValueError instead of crashing with "issubclass() arg 1 must be a class"
|
|
351
|
+
assert "Unexpected graph type:" in str(exc_info.value)
|
|
352
|
+
assert "<class 'str'>" in str(exc_info.value)
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
def test_resolve_graph__non_class_value():
|
|
356
|
+
"""Test that _resolve_graph properly handles non-class values without crashing on issubclass()."""
|
|
357
|
+
# GIVEN a non-class value (a string, not a class)
|
|
358
|
+
non_class_value = "not_a_class"
|
|
359
|
+
|
|
360
|
+
# WHEN we call _resolve_graph with a non-class value
|
|
361
|
+
with pytest.raises(ValueError) as exc_info:
|
|
362
|
+
BaseWorkflow._resolve_graph(non_class_value) # type: ignore
|
|
363
|
+
|
|
364
|
+
# THEN it should raise ValueError instead of crashing with "issubclass() arg 1 must be a class"
|
|
365
|
+
assert "Unexpected graph type:" in str(exc_info.value)
|
|
366
|
+
assert "<class 'str'>" in str(exc_info.value)
|
|
367
|
+
|
|
368
|
+
|
|
343
369
|
def test_base_workflow__deserialize_state():
|
|
344
370
|
# GIVEN a state definition
|
|
345
371
|
class State(BaseState):
|
|
@@ -783,3 +809,28 @@ def test_base_workflow__run_node_with_inputs():
|
|
|
783
809
|
# AND the execution result should use the overridden and non-overridden attributes
|
|
784
810
|
fulfilled_event = events[1]
|
|
785
811
|
assert fulfilled_event.body.outputs.result == "overridden_overridden_value_default_value2_not_overridden"
|
|
812
|
+
|
|
813
|
+
|
|
814
|
+
def test_base_workflow__invalid_graph__outgoing_edge_with_no_ports():
|
|
815
|
+
"""Test that graph construction fails if we attempt to create an outgoing edge from a node with no ports."""
|
|
816
|
+
|
|
817
|
+
# GIVEN
|
|
818
|
+
class StartNode(BaseNode[BaseState]):
|
|
819
|
+
pass
|
|
820
|
+
|
|
821
|
+
class MyFinalOutput(BaseNode[BaseState]):
|
|
822
|
+
class Ports(BaseNode.Ports):
|
|
823
|
+
pass
|
|
824
|
+
|
|
825
|
+
class EndNode(BaseNode[BaseState]):
|
|
826
|
+
pass
|
|
827
|
+
|
|
828
|
+
# THEN
|
|
829
|
+
with pytest.raises(
|
|
830
|
+
ValueError,
|
|
831
|
+
match="Cannot create edges from graph because all terminal nodes have no ports defined: MyFinalOutput. "
|
|
832
|
+
+ "Nodes with empty Ports classes cannot be connected to other nodes.",
|
|
833
|
+
):
|
|
834
|
+
|
|
835
|
+
class InvalidWorkflow(BaseWorkflow[BaseInputs, BaseState]):
|
|
836
|
+
graph = StartNode >> MyFinalOutput >> EndNode
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: vellum-ai
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.13.5
|
|
4
4
|
Summary:
|
|
5
5
|
License: MIT
|
|
6
6
|
Requires-Python: >=3.9,<4.0
|
|
@@ -20,10 +20,14 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.8
|
|
21
21
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
22
|
Classifier: Typing :: Typed
|
|
23
|
+
Provides-Extra: mypy
|
|
24
|
+
Provides-Extra: zuban
|
|
23
25
|
Requires-Dist: Jinja2 (>=3.1.0,<4.0.0)
|
|
24
26
|
Requires-Dist: click (>=8.1.7,<9.0.0)
|
|
25
27
|
Requires-Dist: docker (>=7.1.0,<8.0.0)
|
|
26
28
|
Requires-Dist: httpx (>=0.21.2)
|
|
29
|
+
Requires-Dist: jsonschema (>=4.0.0)
|
|
30
|
+
Requires-Dist: mypy (>=1.13.0) ; extra == "mypy"
|
|
27
31
|
Requires-Dist: orderly-set (>=5.2.2,<6.0.0)
|
|
28
32
|
Requires-Dist: publication (==0.0.3)
|
|
29
33
|
Requires-Dist: pydantic (>=1.9.2)
|
|
@@ -36,6 +40,7 @@ Requires-Dist: pyyaml (>=6.0.0,<7.0.0)
|
|
|
36
40
|
Requires-Dist: requests (>=2.31.0,<3.0.0)
|
|
37
41
|
Requires-Dist: tomli (>=2.0.0,<3.0.0)
|
|
38
42
|
Requires-Dist: typing_extensions (>=4.0.0)
|
|
43
|
+
Requires-Dist: zuban (>=0.4.2) ; extra == "zuban"
|
|
39
44
|
Project-URL: Repository, https://github.com/vellum-ai/vellum-python-sdks
|
|
40
45
|
Description-Content-Type: text/markdown
|
|
41
46
|
|