vellum-ai 1.7.2__py3-none-any.whl → 1.7.4__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.
- vellum/client/core/client_wrapper.py +2 -2
- vellum/client/core/pydantic_utilities.py +8 -1
- vellum/plugins/pydantic.py +1 -0
- vellum/workflows/errors/types.py +5 -1
- vellum/workflows/events/tests/test_event.py +1 -0
- vellum/workflows/exceptions.py +9 -1
- vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +11 -1
- vellum/workflows/nodes/displayable/tool_calling_node/tests/test_node.py +50 -0
- vellum/workflows/nodes/displayable/tool_calling_node/utils.py +13 -6
- vellum/workflows/resolvers/resolver.py +14 -9
- vellum/workflows/runner/runner.py +82 -18
- vellum/workflows/types/__init__.py +2 -1
- vellum/workflows/types/core.py +4 -0
- {vellum_ai-1.7.2.dist-info → vellum_ai-1.7.4.dist-info}/METADATA +1 -1
- {vellum_ai-1.7.2.dist-info → vellum_ai-1.7.4.dist-info}/RECORD +18 -18
- {vellum_ai-1.7.2.dist-info → vellum_ai-1.7.4.dist-info}/LICENSE +0 -0
- {vellum_ai-1.7.2.dist-info → vellum_ai-1.7.4.dist-info}/WHEEL +0 -0
- {vellum_ai-1.7.2.dist-info → vellum_ai-1.7.4.dist-info}/entry_points.txt +0 -0
@@ -27,10 +27,10 @@ class BaseClientWrapper:
|
|
27
27
|
|
28
28
|
def get_headers(self) -> typing.Dict[str, str]:
|
29
29
|
headers: typing.Dict[str, str] = {
|
30
|
-
"User-Agent": "vellum-ai/1.7.
|
30
|
+
"User-Agent": "vellum-ai/1.7.4",
|
31
31
|
"X-Fern-Language": "Python",
|
32
32
|
"X-Fern-SDK-Name": "vellum-ai",
|
33
|
-
"X-Fern-SDK-Version": "1.7.
|
33
|
+
"X-Fern-SDK-Version": "1.7.4",
|
34
34
|
**(self.get_custom_headers() or {}),
|
35
35
|
}
|
36
36
|
if self._api_version is not None:
|
@@ -158,7 +158,14 @@ class UniversalBaseModel(pydantic.BaseModel):
|
|
158
158
|
|
159
159
|
dict_dump = super().dict(**kwargs_with_defaults_exclude_unset_include_fields)
|
160
160
|
|
161
|
-
|
161
|
+
# Skip expensive annotation metadata conversion for types that don't require it.
|
162
|
+
# This optimization dramatically improves serialization performance for large nested
|
163
|
+
# structures by avoiding repeated typing.get_origin checks on every element.
|
164
|
+
if self.__class__.__name__ in annotated_types:
|
165
|
+
return convert_and_respect_annotation_metadata(
|
166
|
+
object_=dict_dump, annotation=self.__class__, direction="write"
|
167
|
+
)
|
168
|
+
return dict_dump
|
162
169
|
|
163
170
|
|
164
171
|
def _union_list_of_pydantic_dicts(source: List[Any], destination: List[Any]) -> List[Any]:
|
vellum/plugins/pydantic.py
CHANGED
@@ -48,6 +48,7 @@ class OnValidatePython(ValidatePythonHandlerProtocol):
|
|
48
48
|
from_attributes: Optional[bool] = None,
|
49
49
|
context: Optional[Dict[str, Any]] = None,
|
50
50
|
self_instance: Optional[Any] = None,
|
51
|
+
extra: Optional[Literal["allow", "ignore", "forbid"]] = None,
|
51
52
|
allow_partial: Union[bool, Literal["off", "on", "trailing-strings"]] = False,
|
52
53
|
by_alias: Optional[bool] = None,
|
53
54
|
by_name: Optional[bool] = None,
|
vellum/workflows/errors/types.py
CHANGED
@@ -33,6 +33,7 @@ class WorkflowError:
|
|
33
33
|
message: str
|
34
34
|
code: WorkflowErrorCode
|
35
35
|
raw_data: Optional[Dict[str, Any]] = None
|
36
|
+
stacktrace: Optional[str] = None
|
36
37
|
|
37
38
|
def __contains__(self, item: Any) -> bool:
|
38
39
|
return item in self.message
|
@@ -43,6 +44,7 @@ _VELLUM_ERROR_CODE_TO_WORKFLOW_ERROR_CODE: Dict[VellumErrorCodeEnum, WorkflowErr
|
|
43
44
|
"INVALID_INPUTS": WorkflowErrorCode.INVALID_INPUTS,
|
44
45
|
"PROVIDER_ERROR": WorkflowErrorCode.PROVIDER_ERROR,
|
45
46
|
"PROVIDER_CREDENTIALS_UNAVAILABLE": WorkflowErrorCode.PROVIDER_CREDENTIALS_UNAVAILABLE,
|
47
|
+
"INTEGRATION_CREDENTIALS_UNAVAILABLE": WorkflowErrorCode.INTEGRATION_CREDENTIALS_UNAVAILABLE,
|
46
48
|
"REQUEST_TIMEOUT": WorkflowErrorCode.PROVIDER_ERROR,
|
47
49
|
"INTERNAL_SERVER_ERROR": WorkflowErrorCode.INTERNAL_ERROR,
|
48
50
|
"USER_DEFINED_ERROR": WorkflowErrorCode.USER_DEFINED_ERROR,
|
@@ -81,6 +83,8 @@ def workflow_event_error_to_workflow_error(error: WorkflowEventError) -> Workflo
|
|
81
83
|
return WorkflowError(
|
82
84
|
message=error.message,
|
83
85
|
code=_WORKFLOW_EVENT_ERROR_CODE_TO_WORKFLOW_ERROR_CODE.get(error.code, WorkflowErrorCode.INTERNAL_ERROR),
|
86
|
+
raw_data=error.raw_data,
|
87
|
+
stacktrace=error.stacktrace,
|
84
88
|
)
|
85
89
|
|
86
90
|
|
@@ -95,7 +99,7 @@ _WORKFLOW_ERROR_CODE_TO_VELLUM_ERROR_CODE: Dict[WorkflowErrorCode, VellumErrorCo
|
|
95
99
|
WorkflowErrorCode.NODE_EXECUTION: "USER_DEFINED_ERROR",
|
96
100
|
WorkflowErrorCode.PROVIDER_ERROR: "PROVIDER_ERROR",
|
97
101
|
WorkflowErrorCode.PROVIDER_CREDENTIALS_UNAVAILABLE: "PROVIDER_CREDENTIALS_UNAVAILABLE",
|
98
|
-
WorkflowErrorCode.INTEGRATION_CREDENTIALS_UNAVAILABLE: "
|
102
|
+
WorkflowErrorCode.INTEGRATION_CREDENTIALS_UNAVAILABLE: "INTEGRATION_CREDENTIALS_UNAVAILABLE",
|
99
103
|
WorkflowErrorCode.USER_DEFINED_ERROR: "USER_DEFINED_ERROR",
|
100
104
|
WorkflowErrorCode.WORKFLOW_CANCELLED: "REQUEST_TIMEOUT",
|
101
105
|
}
|
vellum/workflows/exceptions.py
CHANGED
@@ -25,10 +25,12 @@ class NodeException(Exception):
|
|
25
25
|
message: str,
|
26
26
|
code: WorkflowErrorCode = WorkflowErrorCode.INTERNAL_ERROR,
|
27
27
|
raw_data: Optional[Dict[str, Any]] = None,
|
28
|
+
stacktrace: Optional[str] = None,
|
28
29
|
):
|
29
30
|
self.message = message
|
30
31
|
self.code = code
|
31
32
|
self.raw_data = raw_data
|
33
|
+
self.stacktrace = stacktrace
|
32
34
|
super().__init__(message)
|
33
35
|
|
34
36
|
@property
|
@@ -37,11 +39,17 @@ class NodeException(Exception):
|
|
37
39
|
message=self.message,
|
38
40
|
code=self.code,
|
39
41
|
raw_data=self.raw_data,
|
42
|
+
stacktrace=self.stacktrace,
|
40
43
|
)
|
41
44
|
|
42
45
|
@staticmethod
|
43
46
|
def of(workflow_error: WorkflowError) -> "NodeException":
|
44
|
-
return NodeException(
|
47
|
+
return NodeException(
|
48
|
+
message=workflow_error.message,
|
49
|
+
code=workflow_error.code,
|
50
|
+
raw_data=workflow_error.raw_data,
|
51
|
+
stacktrace=workflow_error.stacktrace,
|
52
|
+
)
|
45
53
|
|
46
54
|
|
47
55
|
class WorkflowInitializationException(Exception):
|
@@ -21,7 +21,7 @@ from vellum.workflows.errors import WorkflowErrorCode
|
|
21
21
|
from vellum.workflows.errors.types import workflow_event_error_to_workflow_error
|
22
22
|
from vellum.workflows.events.types import default_serializer
|
23
23
|
from vellum.workflows.events.workflow import is_workflow_event
|
24
|
-
from vellum.workflows.exceptions import NodeException
|
24
|
+
from vellum.workflows.exceptions import NodeException, WorkflowInitializationException
|
25
25
|
from vellum.workflows.inputs.base import BaseInputs
|
26
26
|
from vellum.workflows.nodes.bases.base import BaseNode
|
27
27
|
from vellum.workflows.outputs.base import BaseOutput
|
@@ -164,6 +164,16 @@ class SubworkflowDeploymentNode(BaseNode[StateType], Generic[StateType]):
|
|
164
164
|
node_output_mocks=self._context._get_all_node_output_mocks(),
|
165
165
|
)
|
166
166
|
|
167
|
+
try:
|
168
|
+
next(subworkflow_stream)
|
169
|
+
except WorkflowInitializationException as e:
|
170
|
+
hashed_module = e.definition.__module__
|
171
|
+
raise NodeException(
|
172
|
+
message=e.message,
|
173
|
+
code=e.code,
|
174
|
+
raw_data={"hashed_module": hashed_module},
|
175
|
+
) from e
|
176
|
+
|
167
177
|
outputs = None
|
168
178
|
exception = None
|
169
179
|
fulfilled_output_names: Set[str] = set()
|
@@ -24,6 +24,7 @@ from vellum.workflows.nodes.displayable.tool_calling_node.utils import (
|
|
24
24
|
create_tool_prompt_node,
|
25
25
|
)
|
26
26
|
from vellum.workflows.outputs.base import BaseOutputs
|
27
|
+
from vellum.workflows.ports.utils import validate_ports
|
27
28
|
from vellum.workflows.state.base import BaseState, StateMeta
|
28
29
|
from vellum.workflows.state.context import WorkflowContext
|
29
30
|
from vellum.workflows.types.definition import DeploymentDefinition
|
@@ -38,6 +39,55 @@ def second_function() -> str:
|
|
38
39
|
return "second_function"
|
39
40
|
|
40
41
|
|
42
|
+
def test_router_node_port_ordering_with_multiple_tools():
|
43
|
+
"""
|
44
|
+
Test that router node ports are created in the correct order: on_if, on_elif, ..., on_else.
|
45
|
+
|
46
|
+
This test validates the fix for the bug where multiple tools would create multiple on_if
|
47
|
+
ports instead of on_if followed by on_elif ports, which violates port validation rules.
|
48
|
+
"""
|
49
|
+
|
50
|
+
# GIVEN three functions to ensure we test multiple elif cases
|
51
|
+
def third_function() -> str:
|
52
|
+
return "third_function"
|
53
|
+
|
54
|
+
# AND a tool prompt node
|
55
|
+
tool_prompt_node = create_tool_prompt_node(
|
56
|
+
ml_model="test-model",
|
57
|
+
blocks=[],
|
58
|
+
functions=[first_function, second_function, third_function],
|
59
|
+
prompt_inputs=None,
|
60
|
+
parameters=DEFAULT_PROMPT_PARAMETERS,
|
61
|
+
)
|
62
|
+
|
63
|
+
# WHEN a router node is created with multiple functions
|
64
|
+
router_node = create_router_node(
|
65
|
+
functions=[first_function, second_function, third_function],
|
66
|
+
tool_prompt_node=tool_prompt_node,
|
67
|
+
)
|
68
|
+
|
69
|
+
# THEN the first function port should be an on_if port
|
70
|
+
first_function_port = getattr(router_node.Ports, "first_function")
|
71
|
+
assert first_function_port._condition_type.value == "IF"
|
72
|
+
|
73
|
+
# AND the second function port should be an on_elif port
|
74
|
+
second_function_port = getattr(router_node.Ports, "second_function")
|
75
|
+
assert second_function_port._condition_type.value == "ELIF"
|
76
|
+
|
77
|
+
# AND the third function port should also be an on_elif port
|
78
|
+
third_function_port = getattr(router_node.Ports, "third_function")
|
79
|
+
assert third_function_port._condition_type.value == "ELIF"
|
80
|
+
|
81
|
+
# AND the default port should be an on_else port
|
82
|
+
default_port = getattr(router_node.Ports, "default")
|
83
|
+
assert default_port._condition_type.value == "ELSE"
|
84
|
+
|
85
|
+
# AND the ports should pass validation
|
86
|
+
ports = [first_function_port, second_function_port, third_function_port, default_port]
|
87
|
+
# This should not raise an exception
|
88
|
+
validate_ports(ports)
|
89
|
+
|
90
|
+
|
41
91
|
def test_port_condition_match_function_name():
|
42
92
|
"""
|
43
93
|
Test that the port condition correctly matches the function name.
|
@@ -409,8 +409,8 @@ def create_router_node(
|
|
409
409
|
# Avoid using lambda to capture function_name
|
410
410
|
# lambda will capture the function_name by reference,
|
411
411
|
# and if the function_name is changed, the port_condition will also change.
|
412
|
-
def create_port_condition(fn_name):
|
413
|
-
|
412
|
+
def create_port_condition(fn_name, is_first):
|
413
|
+
condition = (
|
414
414
|
ToolCallingState.current_prompt_output_index.less_than(tool_prompt_node.Outputs.results.length())
|
415
415
|
& tool_prompt_node.Outputs.results[ToolCallingState.current_prompt_output_index]["type"].equals(
|
416
416
|
"FUNCTION_CALL"
|
@@ -419,26 +419,33 @@ def create_router_node(
|
|
419
419
|
"name"
|
420
420
|
].equals(fn_name)
|
421
421
|
)
|
422
|
+
# First port should be on_if, subsequent ports should be on_elif
|
423
|
+
return Port.on_if(condition) if is_first else Port.on_elif(condition)
|
422
424
|
|
425
|
+
is_first_port = True
|
423
426
|
for function in functions:
|
424
427
|
if isinstance(function, ComposioToolDefinition):
|
425
428
|
function_name = get_function_name(function)
|
426
|
-
port = create_port_condition(function_name)
|
429
|
+
port = create_port_condition(function_name, is_first_port)
|
427
430
|
setattr(Ports, function_name, port)
|
431
|
+
is_first_port = False
|
428
432
|
elif isinstance(function, VellumIntegrationToolDefinition):
|
429
433
|
function_name = get_function_name(function)
|
430
|
-
port = create_port_condition(function_name)
|
434
|
+
port = create_port_condition(function_name, is_first_port)
|
431
435
|
setattr(Ports, function_name, port)
|
436
|
+
is_first_port = False
|
432
437
|
elif isinstance(function, MCPServer):
|
433
438
|
tool_functions: List[MCPToolDefinition] = compile_mcp_tool_definition(function)
|
434
439
|
for tool_function in tool_functions:
|
435
440
|
name = get_mcp_tool_name(tool_function)
|
436
|
-
port = create_port_condition(name)
|
441
|
+
port = create_port_condition(name, is_first_port)
|
437
442
|
setattr(Ports, name, port)
|
443
|
+
is_first_port = False
|
438
444
|
else:
|
439
445
|
function_name = get_function_name(function)
|
440
|
-
port = create_port_condition(function_name)
|
446
|
+
port = create_port_condition(function_name, is_first_port)
|
441
447
|
setattr(Ports, function_name, port)
|
448
|
+
is_first_port = False
|
442
449
|
|
443
450
|
# Add the else port for when no function conditions match
|
444
451
|
setattr(Ports, "default", Port.on_else())
|
@@ -52,15 +52,6 @@ class VellumResolver(BaseWorkflowResolver):
|
|
52
52
|
if response.state is None:
|
53
53
|
return None
|
54
54
|
|
55
|
-
if (
|
56
|
-
response.previous_trace_id is None
|
57
|
-
or response.root_trace_id is None
|
58
|
-
or response.previous_span_id is None
|
59
|
-
or response.root_span_id is None
|
60
|
-
):
|
61
|
-
logger.warning("Could not find required execution events for state loading")
|
62
|
-
return None
|
63
|
-
|
64
55
|
if "meta" in response.state:
|
65
56
|
response.state.pop("meta")
|
66
57
|
|
@@ -71,6 +62,20 @@ class VellumResolver(BaseWorkflowResolver):
|
|
71
62
|
logger.warning("No workflow class registered, falling back to BaseState")
|
72
63
|
state = BaseState(**response.state)
|
73
64
|
|
65
|
+
if (
|
66
|
+
response.previous_trace_id is None
|
67
|
+
or response.root_trace_id is None
|
68
|
+
or response.previous_span_id is None
|
69
|
+
or response.root_span_id is None
|
70
|
+
):
|
71
|
+
return LoadStateResult(
|
72
|
+
state=state,
|
73
|
+
previous_trace_id=response.trace_id,
|
74
|
+
previous_span_id=response.span_id,
|
75
|
+
root_trace_id=response.trace_id,
|
76
|
+
root_span_id=response.span_id,
|
77
|
+
)
|
78
|
+
|
74
79
|
return LoadStateResult(
|
75
80
|
state=state,
|
76
81
|
previous_trace_id=response.previous_trace_id,
|
@@ -1,4 +1,5 @@
|
|
1
1
|
from collections import defaultdict
|
2
|
+
from contextlib import contextmanager
|
2
3
|
from copy import deepcopy
|
3
4
|
from dataclasses import dataclass
|
4
5
|
import logging
|
@@ -232,7 +233,33 @@ class WorkflowRunner(Generic[StateType]):
|
|
232
233
|
|
233
234
|
self._background_thread: Optional[Thread] = None
|
234
235
|
self._cancel_thread: Optional[Thread] = None
|
235
|
-
|
236
|
+
|
237
|
+
@contextmanager
|
238
|
+
def _httpx_logger_with_span_id(self) -> Iterator[None]:
|
239
|
+
"""
|
240
|
+
Context manager to append the current execution's span ID to httpx logger messages.
|
241
|
+
|
242
|
+
This is used when making API requests via the Vellum client to include
|
243
|
+
the execution's span ID in the httpx request logs for better traceability.
|
244
|
+
"""
|
245
|
+
httpx_logger = logging.getLogger("httpx")
|
246
|
+
|
247
|
+
class SpanIdFilter(logging.Filter):
|
248
|
+
def filter(self, record: logging.LogRecord) -> bool:
|
249
|
+
if record.name == "httpx" and "[span_id=" not in record.msg:
|
250
|
+
context = get_execution_context()
|
251
|
+
if context.parent_context:
|
252
|
+
span_id = str(context.parent_context.span_id)
|
253
|
+
record.msg = f"{record.msg} [span_id={span_id}]"
|
254
|
+
return True
|
255
|
+
|
256
|
+
span_filter = SpanIdFilter()
|
257
|
+
httpx_logger.addFilter(span_filter)
|
258
|
+
|
259
|
+
try:
|
260
|
+
yield
|
261
|
+
finally:
|
262
|
+
httpx_logger.removeFilter(span_filter)
|
236
263
|
|
237
264
|
def _snapshot_state(self, state: StateType, deltas: List[StateDelta]) -> StateType:
|
238
265
|
self._workflow_event_inner_queue.put(
|
@@ -695,6 +722,36 @@ class WorkflowRunner(Generic[StateType]):
|
|
695
722
|
|
696
723
|
return None
|
697
724
|
|
725
|
+
def _emit_node_cancellation_events(
|
726
|
+
self,
|
727
|
+
error_message: str,
|
728
|
+
parent_context: Optional[ParentContext],
|
729
|
+
) -> None:
|
730
|
+
"""
|
731
|
+
Emit node cancellation events for all active nodes.
|
732
|
+
|
733
|
+
Args:
|
734
|
+
error_message: The error message to include in the cancellation events
|
735
|
+
parent_context: The parent context for the cancellation events
|
736
|
+
"""
|
737
|
+
captured_stacktrace = "".join(traceback.format_stack())
|
738
|
+
for span_id, active_node in list(self._active_nodes_by_execution_id.items()):
|
739
|
+
rejection_event = NodeExecutionRejectedEvent(
|
740
|
+
trace_id=self._execution_context.trace_id,
|
741
|
+
span_id=span_id,
|
742
|
+
body=NodeExecutionRejectedBody(
|
743
|
+
node_definition=active_node.node.__class__,
|
744
|
+
error=WorkflowError(
|
745
|
+
code=WorkflowErrorCode.NODE_CANCELLED,
|
746
|
+
message=error_message,
|
747
|
+
),
|
748
|
+
stacktrace=captured_stacktrace,
|
749
|
+
),
|
750
|
+
parent=parent_context,
|
751
|
+
)
|
752
|
+
self._workflow_event_outer_queue.put(rejection_event)
|
753
|
+
self._active_nodes_by_execution_id.pop(span_id)
|
754
|
+
|
698
755
|
def _initiate_workflow_event(self) -> WorkflowExecutionInitiatedEvent:
|
699
756
|
links: Optional[List[SpanLink]] = None
|
700
757
|
|
@@ -796,6 +853,11 @@ class WorkflowRunner(Generic[StateType]):
|
|
796
853
|
parent=self._execution_context.parent_context,
|
797
854
|
)
|
798
855
|
|
856
|
+
def _wrapped_stream(self) -> None:
|
857
|
+
"""Wrapper for _stream that adds httpx logger span ID context."""
|
858
|
+
with self._httpx_logger_with_span_id():
|
859
|
+
self._stream()
|
860
|
+
|
799
861
|
def _stream(self) -> None:
|
800
862
|
for edge in self.workflow.get_edges():
|
801
863
|
self._dependencies[edge.to_node].add(edge.from_port.node_class)
|
@@ -848,21 +910,10 @@ class WorkflowRunner(Generic[StateType]):
|
|
848
910
|
|
849
911
|
if rejection_event:
|
850
912
|
failed_node_name = rejection_event.body.node_definition.__name__
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
body=NodeExecutionRejectedBody(
|
856
|
-
node_definition=active_node_data.node.__class__,
|
857
|
-
error=WorkflowError(
|
858
|
-
message=f"Node execution cancelled due to {failed_node_name} failure",
|
859
|
-
code=WorkflowErrorCode.NODE_CANCELLED,
|
860
|
-
),
|
861
|
-
),
|
862
|
-
parent=self._execution_context.parent_context,
|
863
|
-
)
|
864
|
-
self._workflow_event_outer_queue.put(cancellation_event)
|
865
|
-
self._active_nodes_by_execution_id.pop(active_span_id)
|
913
|
+
self._emit_node_cancellation_events(
|
914
|
+
error_message=f"Node execution cancelled due to {failed_node_name} failure",
|
915
|
+
parent_context=self._execution_context.parent_context,
|
916
|
+
)
|
866
917
|
break
|
867
918
|
|
868
919
|
# Handle any remaining events
|
@@ -932,12 +983,25 @@ class WorkflowRunner(Generic[StateType]):
|
|
932
983
|
|
933
984
|
while not kill_switch.wait(timeout=0.1):
|
934
985
|
if self._cancel_signal.is_set():
|
986
|
+
parent_context = WorkflowParentContext(
|
987
|
+
span_id=self._initial_state.meta.span_id,
|
988
|
+
workflow_definition=self.workflow.__class__,
|
989
|
+
parent=self._execution_context.parent_context,
|
990
|
+
)
|
991
|
+
|
992
|
+
self._emit_node_cancellation_events(
|
993
|
+
error_message="Workflow run cancelled",
|
994
|
+
parent_context=parent_context,
|
995
|
+
)
|
996
|
+
|
997
|
+
captured_stacktrace = "".join(traceback.format_stack())
|
935
998
|
self._workflow_event_outer_queue.put(
|
936
999
|
self._reject_workflow_event(
|
937
1000
|
WorkflowError(
|
938
1001
|
code=WorkflowErrorCode.WORKFLOW_CANCELLED,
|
939
1002
|
message="Workflow run cancelled",
|
940
|
-
)
|
1003
|
+
),
|
1004
|
+
captured_stacktrace,
|
941
1005
|
)
|
942
1006
|
)
|
943
1007
|
return
|
@@ -977,7 +1041,7 @@ class WorkflowRunner(Generic[StateType]):
|
|
977
1041
|
|
978
1042
|
# The extra level of indirection prevents the runner from waiting on the caller to consume the event stream
|
979
1043
|
self._stream_thread = Thread(
|
980
|
-
target=self.
|
1044
|
+
target=self._wrapped_stream,
|
981
1045
|
name=f"{self.workflow.__class__.__name__}.stream_thread",
|
982
1046
|
)
|
983
1047
|
self._stream_thread.start()
|
vellum/workflows/types/core.py
CHANGED
@@ -1,4 +1,6 @@
|
|
1
1
|
from enum import Enum
|
2
|
+
from multiprocessing.synchronize import Event as MultiprocessingEvent
|
3
|
+
from threading import Event as ThreadingEvent
|
2
4
|
from typing import ( # type: ignore[attr-defined]
|
3
5
|
Any,
|
4
6
|
Dict,
|
@@ -15,6 +17,8 @@ JsonArray = List["Json"]
|
|
15
17
|
JsonObject = Dict[str, "Json"]
|
16
18
|
Json = Union[None, bool, int, float, str, JsonArray, JsonObject]
|
17
19
|
|
20
|
+
CancelSignal = Union[ThreadingEvent, MultiprocessingEvent]
|
21
|
+
|
18
22
|
# Unions and Generics inherit from `_GenericAlias` instead of `type`
|
19
23
|
# In future versions of python, we'll see `_UnionGenericAlias`
|
20
24
|
UnderGenericAlias = _GenericAlias
|
@@ -160,14 +160,14 @@ vellum/client/README.md,sha256=flqu57ubZNTfpq60CdLtJC9gp4WEkyjb_n_eZ4OYf9w,6497
|
|
160
160
|
vellum/client/__init__.py,sha256=rMnKRqL5-356SBc-rfm56MkO87PuAi2mtcfBszcJU1M,74316
|
161
161
|
vellum/client/core/__init__.py,sha256=lTcqUPXcx4112yLDd70RAPeqq6tu3eFMe1pKOqkW9JQ,1562
|
162
162
|
vellum/client/core/api_error.py,sha256=44vPoTyWN59gonCIZMdzw7M1uspygiLnr3GNFOoVL2Q,614
|
163
|
-
vellum/client/core/client_wrapper.py,sha256=
|
163
|
+
vellum/client/core/client_wrapper.py,sha256=l3m9Q8u_-eKF93ekwPZtf7Z2S1yy8YrttUS-JF-zwc8,2840
|
164
164
|
vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
|
165
165
|
vellum/client/core/file.py,sha256=d4NNbX8XvXP32z8KpK2Xovv33nFfruIrpz0QWxlgpZk,2663
|
166
166
|
vellum/client/core/force_multipart.py,sha256=awxh5MtcRYe74ehY8U76jzv6fYM_w_D3Rur7KQQzSDk,429
|
167
167
|
vellum/client/core/http_client.py,sha256=QurkBvCZZz2Z1d8znp4M2YbOXebBUPcPXRhPIS84Wvk,21214
|
168
168
|
vellum/client/core/http_response.py,sha256=4uOAtXXFTyFXHLXeQWSfQST9PGcOCRAdHVgGTxdyg84,1334
|
169
169
|
vellum/client/core/jsonable_encoder.py,sha256=hGgcEEeX11sqxxsll7h15pO3pTNVxk_n79Kcn0laoWA,3655
|
170
|
-
vellum/client/core/pydantic_utilities.py,sha256=
|
170
|
+
vellum/client/core/pydantic_utilities.py,sha256=y9CLy3XanCrFf-pJL11IieMQ9ntPIJG45xnFjTLfVUs,11784
|
171
171
|
vellum/client/core/query_encoder.py,sha256=ekulqNd0j8TgD7ox-Qbz7liqX8-KP9blvT9DsRCenYM,2144
|
172
172
|
vellum/client/core/remove_none_from_dict.py,sha256=EU9SGgYidWq7SexuJbNs4-PZ-5Bl3Vppd864mS6vQZw,342
|
173
173
|
vellum/client/core/request_options.py,sha256=h0QUNCFVdCW_7GclVySCAY2w4NhtXVBUCmHgmzaxpcg,1681
|
@@ -988,7 +988,7 @@ vellum/evaluations/utils/env.py,sha256=Xj_nxsoU5ox06EOTjRopR4lrigQI6Le6qbWGltYoE
|
|
988
988
|
vellum/evaluations/utils/exceptions.py,sha256=dXMAkzqbHV_AP5FjjbegPlfUE0zQDlpA3qOsoOJUxfg,49
|
989
989
|
vellum/evaluations/utils/paginator.py,sha256=rEED_BJAXAM6tM1yMwHePNzszjq_tTq4NbQvi1jWQ_Q,697
|
990
990
|
vellum/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
991
|
-
vellum/plugins/pydantic.py,sha256
|
991
|
+
vellum/plugins/pydantic.py,sha256=-AV02TCdI3Uk4cgB2jO-YhQcRqvylb3g-h1ytKaRwvg,3981
|
992
992
|
vellum/plugins/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
993
993
|
vellum/plugins/tests/test_pydantic.py,sha256=S6bLqs3Y5DGA012QV_7f6hk4e6Bz-iJ9py9DEKuo4fM,746
|
994
994
|
vellum/plugins/utils.py,sha256=cPmxE9R2CK1bki2jKE8rB-G9zMf2pzHjSPDHFPXwd3Q,878
|
@@ -1804,7 +1804,7 @@ vellum/workflows/emitters/vellum_emitter.py,sha256=t4ixrN0NNXrydMP9PVKYvcOMxoMqs
|
|
1804
1804
|
vellum/workflows/environment/__init__.py,sha256=TJz0m9dwIs6YOwCTeuN0HHsU-ecyjc1OJXx4AFy83EQ,121
|
1805
1805
|
vellum/workflows/environment/environment.py,sha256=Ck3RPKXJvtMGx_toqYQQQF-ZwXm5ijVwJpEPTeIJ4_Q,471
|
1806
1806
|
vellum/workflows/errors/__init__.py,sha256=tWGPu5xyAU8gRb8_bl0fL7OfU3wxQ9UH6qVwy4X4P_Q,113
|
1807
|
-
vellum/workflows/errors/types.py,sha256=
|
1807
|
+
vellum/workflows/errors/types.py,sha256=N43BsnhnYZvuPql-Xu86Y6QQ07BxKv5ypD2lq4eugpk,4749
|
1808
1808
|
vellum/workflows/events/__init__.py,sha256=V4mh766fyA70WvHelm9kfVZGrUgEKcJ9tJt8EepfQYU,832
|
1809
1809
|
vellum/workflows/events/context.py,sha256=vCfMIPmz4j9Om36rRWa35A_JU_VccWWS52_mZkkqxak,3345
|
1810
1810
|
vellum/workflows/events/exception_handling.py,sha256=2okFtCzrOzaCP-HEwBPMvHn-evlyyE1zRkmIYjR__jQ,1975
|
@@ -1813,10 +1813,10 @@ vellum/workflows/events/relational_threads.py,sha256=zmLrBCBYpdpQV0snKH3HleST-_h
|
|
1813
1813
|
vellum/workflows/events/stream.py,sha256=xhXJTZirFi0xad5neAQNogrIQ4h47fpnKbVC3vCM5Js,889
|
1814
1814
|
vellum/workflows/events/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1815
1815
|
vellum/workflows/events/tests/test_basic_workflow.py,sha256=Pj6orHsXz37jWC5FARi0Sx2Gjf99Owri2Cvr6Chb79k,1765
|
1816
|
-
vellum/workflows/events/tests/test_event.py,sha256=
|
1816
|
+
vellum/workflows/events/tests/test_event.py,sha256=rwbS8W1wriN6EDt_NlFA1HgSAqgBbEyCU63gfjCowrM,19736
|
1817
1817
|
vellum/workflows/events/types.py,sha256=mVrqAH9Hs9SpXm08Hcxdyap_ImQPwGsxRr56rSNMP34,5043
|
1818
1818
|
vellum/workflows/events/workflow.py,sha256=kLSWFXiDZH0TELWoDjQ_kHVomFnw8MVVUPDGIzgyosw,8997
|
1819
|
-
vellum/workflows/exceptions.py,sha256=
|
1819
|
+
vellum/workflows/exceptions.py,sha256=cizNaHgmGdIoYSV3Mn6_HlpUvs2Nq9KgpX1ewMZdBa0,2157
|
1820
1820
|
vellum/workflows/executable.py,sha256=um-gLJMVYfGJwGJfZIPlCRHhHIYm6pn8PUEfeqrNx5k,218
|
1821
1821
|
vellum/workflows/expressions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1822
1822
|
vellum/workflows/expressions/accessor.py,sha256=3lu1-_-dBfZdJvtX-q66jbmRAZtqIfdsh_3_JNuzg1E,4462
|
@@ -1966,7 +1966,7 @@ vellum/workflows/nodes/displayable/search_node/node.py,sha256=1dGCB1kb7MvX3fUJ5z
|
|
1966
1966
|
vellum/workflows/nodes/displayable/search_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1967
1967
|
vellum/workflows/nodes/displayable/search_node/tests/test_node.py,sha256=WVZR3BI_CvxBG9hulv0-tcAc_gW5ozs0nH4uVNRJa2U,8863
|
1968
1968
|
vellum/workflows/nodes/displayable/subworkflow_deployment_node/__init__.py,sha256=9yYM6001YZeqI1VOk1QuEM_yrffk_EdsO7qaPzINKds,92
|
1969
|
-
vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py,sha256=
|
1969
|
+
vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py,sha256=SZIdk7aBmKKFgPYsxZaHIjT6p5W9HBYT1lj5yE4oax8,14169
|
1970
1970
|
vellum/workflows/nodes/displayable/subworkflow_deployment_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1971
1971
|
vellum/workflows/nodes/displayable/subworkflow_deployment_node/tests/test_node.py,sha256=c98nMPogZ6iN_pTvVUMTB3J72Hj--H-XVgvvRXhdSQE,19085
|
1972
1972
|
vellum/workflows/nodes/displayable/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -1979,9 +1979,9 @@ vellum/workflows/nodes/displayable/tool_calling_node/node.py,sha256=pwK9q1blgRv9
|
|
1979
1979
|
vellum/workflows/nodes/displayable/tool_calling_node/state.py,sha256=CcBVb_YtwfSSka4ze678k6-qwmzMSfjfVP8_Y95feSo,302
|
1980
1980
|
vellum/workflows/nodes/displayable/tool_calling_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1981
1981
|
vellum/workflows/nodes/displayable/tool_calling_node/tests/test_composio_service.py,sha256=in1fbEz5x1tx3uKv9YXdvOncsHucNL8Ro6Go7lBuuOQ,8962
|
1982
|
-
vellum/workflows/nodes/displayable/tool_calling_node/tests/test_node.py,sha256=
|
1982
|
+
vellum/workflows/nodes/displayable/tool_calling_node/tests/test_node.py,sha256=Idjtlly6GTotNa4isXJ23RxKzQA2oE10MOm793aipLA,13892
|
1983
1983
|
vellum/workflows/nodes/displayable/tool_calling_node/tests/test_utils.py,sha256=EmKFA-ELdTzlK0xMqWnuSZPoGNLYCwk6b0amTqirZo0,11305
|
1984
|
-
vellum/workflows/nodes/displayable/tool_calling_node/utils.py,sha256=
|
1984
|
+
vellum/workflows/nodes/displayable/tool_calling_node/utils.py,sha256=yIo7xwI43M8wQO8UN4uYxWBWafgcC9e8Ucsp6PZDva4,24518
|
1985
1985
|
vellum/workflows/nodes/displayable/web_search_node/__init__.py,sha256=8FOnEP-n-U68cvxTlJW9wphIAGHq5aqjzLM-DoSSXnU,61
|
1986
1986
|
vellum/workflows/nodes/displayable/web_search_node/node.py,sha256=NQYux2bOtuBF5E4tn-fXi5y3btURPRrNqMSM9MAZYI4,5091
|
1987
1987
|
vellum/workflows/nodes/displayable/web_search_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -2017,11 +2017,11 @@ vellum/workflows/references/vellum_secret.py,sha256=Od4d19a5yletWMqNfJR5d_mZQUkV
|
|
2017
2017
|
vellum/workflows/references/workflow_input.py,sha256=W3rOK1EPd2gYHb04WJwmNm1CUSdvZ9LKrs8RMKxACBs,1751
|
2018
2018
|
vellum/workflows/resolvers/__init__.py,sha256=eH6hTvZO4IciDaf_cf7aM2vs-DkBDyJPycOQevJxQnI,82
|
2019
2019
|
vellum/workflows/resolvers/base.py,sha256=wrQiSC02Bw4-dBwgFjJIHsjpe-4xz4rUJs_1RdErKA0,1164
|
2020
|
-
vellum/workflows/resolvers/resolver.py,sha256=
|
2020
|
+
vellum/workflows/resolvers/resolver.py,sha256=3uEYscB_2PHTazc0Y9SzOe_yiQZhVLfey19hU1HzBaU,3127
|
2021
2021
|
vellum/workflows/resolvers/tests/test_resolver.py,sha256=PnUGzsulo1It_LjjhHsRNiILvvl5G_IaK8ZX56zKC28,6204
|
2022
2022
|
vellum/workflows/resolvers/types.py,sha256=Hndhlk69g6EKLh_LYg5ILepW5U_h_BYNllfzhS9k8p4,237
|
2023
2023
|
vellum/workflows/runner/__init__.py,sha256=i1iG5sAhtpdsrlvwgH6B-m49JsINkiWyPWs8vyT-bqM,72
|
2024
|
-
vellum/workflows/runner/runner.py,sha256=
|
2024
|
+
vellum/workflows/runner/runner.py,sha256=pmqz7zP_YYv7e4kU2WviqHo37SETNyp1FWPscmob8v4,45666
|
2025
2025
|
vellum/workflows/sandbox.py,sha256=mezSZmilR_fwR8164n8CEfzlMeQ55IqfapHp4ftImvQ,3212
|
2026
2026
|
vellum/workflows/state/__init__.py,sha256=yUUdR-_Vl7UiixNDYQZ-GEM_kJI9dnOia75TtuNEsnE,60
|
2027
2027
|
vellum/workflows/state/base.py,sha256=A8s0PC8UvFjPpkHDY6u-yIeb2KHjoAmu-GW-GYrDl0E,24654
|
@@ -2035,9 +2035,9 @@ vellum/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3
|
|
2035
2035
|
vellum/workflows/tests/test_dataset_row.py,sha256=S8aIiYU9TRzJ8GTl5qCjnJ-fuHdxatHJFGLlKTVHPr4,4174
|
2036
2036
|
vellum/workflows/tests/test_sandbox.py,sha256=JKwaluI-lODQo7Ek9sjDstjL_WTdSqUlVik6ZVTfVOA,1826
|
2037
2037
|
vellum/workflows/tests/test_undefined.py,sha256=zMCVliCXVNLrlC6hEGyOWDnQADJ2g83yc5FIM33zuo8,353
|
2038
|
-
vellum/workflows/types/__init__.py,sha256=
|
2038
|
+
vellum/workflows/types/__init__.py,sha256=fZ3Xxly7YSsu4kCIYD5aYpYucNM97zTyInb9CA24mf0,102
|
2039
2039
|
vellum/workflows/types/code_execution_node_wrappers.py,sha256=fewX9bqF_4TZuK-gZYIn12s31-k03vHMGRpvFAPm11Y,3206
|
2040
|
-
vellum/workflows/types/core.py,sha256=
|
2040
|
+
vellum/workflows/types/core.py,sha256=R7snCd7ci4tiRuHi5ALGh_5DIIF0T9eze3sf6EnJN-c,1126
|
2041
2041
|
vellum/workflows/types/definition.py,sha256=Qof2MAjSNB0AN2XkSKmk-owuY59YcxDVHYpno6-StPA,8058
|
2042
2042
|
vellum/workflows/types/generics.py,sha256=8jptbEx1fnJV0Lhj0MpCJOT6yNiEWeTOYOwrEAb5CRU,1576
|
2043
2043
|
vellum/workflows/types/stack.py,sha256=h7NE0vXR7l9DevFBIzIAk1Zh59K-kECQtDTKOUunwMY,1314
|
@@ -2065,8 +2065,8 @@ vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnad
|
|
2065
2065
|
vellum/workflows/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
2066
2066
|
vellum/workflows/workflows/tests/test_base_workflow.py,sha256=Boa-_m9ii2Qsa1RvVM-VYniF7zCpzGgEGy-OnPZkrHg,23941
|
2067
2067
|
vellum/workflows/workflows/tests/test_context.py,sha256=VJBUcyWVtMa_lE5KxdhgMu0WYNYnUQUDvTF7qm89hJ0,2333
|
2068
|
-
vellum_ai-1.7.
|
2069
|
-
vellum_ai-1.7.
|
2070
|
-
vellum_ai-1.7.
|
2071
|
-
vellum_ai-1.7.
|
2072
|
-
vellum_ai-1.7.
|
2068
|
+
vellum_ai-1.7.4.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
|
2069
|
+
vellum_ai-1.7.4.dist-info/METADATA,sha256=sc8YEMq91hq8swhNrwAMqtp-WdoC201YZ6iOf36PxI4,5547
|
2070
|
+
vellum_ai-1.7.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
2071
|
+
vellum_ai-1.7.4.dist-info/entry_points.txt,sha256=xVavzAKN4iF_NbmhWOlOkHluka0YLkbN_pFQ9pW3gLI,117
|
2072
|
+
vellum_ai-1.7.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|