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.
@@ -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.2",
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.2",
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
- return convert_and_respect_annotation_metadata(object_=dict_dump, annotation=self.__class__, direction="write")
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]:
@@ -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,
@@ -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: "PROVIDER_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
  }
@@ -263,6 +263,7 @@ mock_node_uuid = str(uuid4_from_hash(MockNode.__qualname__))
263
263
  "message": "Workflow failed",
264
264
  "code": "USER_DEFINED_ERROR",
265
265
  "raw_data": None,
266
+ "stacktrace": None,
266
267
  },
267
268
  "stacktrace": None,
268
269
  },
@@ -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(message=workflow_error.message, code=workflow_error.code, raw_data=workflow_error.raw_data)
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
- return Port.on_if(
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
- self._stream_thread: Optional[Thread] = None
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
- for active_span_id, active_node_data in list(self._active_nodes_by_execution_id.items()):
852
- cancellation_event = NodeExecutionRejectedEvent(
853
- trace_id=self._execution_context.trace_id,
854
- span_id=active_span_id,
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._stream,
1044
+ target=self._wrapped_stream,
981
1045
  name=f"{self.workflow.__class__.__name__}.stream_thread",
982
1046
  )
983
1047
  self._stream_thread.start()
@@ -1,5 +1,6 @@
1
- from .core import MergeBehavior
1
+ from .core import CancelSignal, MergeBehavior
2
2
 
3
3
  __all__ = [
4
+ "CancelSignal",
4
5
  "MergeBehavior",
5
6
  ]
@@ -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
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vellum-ai
3
- Version: 1.7.2
3
+ Version: 1.7.4
4
4
  Summary:
5
5
  License: MIT
6
6
  Requires-Python: >=3.9,<4.0
@@ -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=4Sfjvux7hceG2zs5IHHn9McKc2YE_WIb9ctx_HfCyzA,2840
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=8evivb_gxrY5VwrEgid4u-HnSmVtkAO5y-B65qYcACU,11403
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=SamPlRZ8V9kuxEfMkOPKjhMMLa5Q3wYJ3Z-F_IfKtvA,3911
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=dmIYCJl2OdQnU5CW_fgKcQy7tERAeddLQ1FSp7gIKeA,4541
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=jsC8APdrddLs5ejk9NO0waPLLslsJlBMIvN0M_vpAHI,19692
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=nb05hAh-afzZ9hek7vhegq-zDtmHopv-4No3aZ-gKO4,1941
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=ZBGOuzAEeMFR7zhIOtXc3Vvv8I4TKZaCFzm_narFc18,13803
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=GZoeybB9uM7ai8sBLAtUMHrMVgh-WrJDWrKZci6feDs,11892
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=NDp2rEU-1QACxrSplocDKlPzILczzvPygkUOrysjU7Y,24109
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=EIIiA2OlaVUPiKiSh6egQZxPA6ny1GDMdPq1AuN-mV8,2961
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=rwMZlQBkzK-EfewC6OysNCeuDeTCfpNuzaUlgYoFJMw,43329
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=KxUTMBGzuRCfiMqzzsykOeVvrrkaZmTTo1a7SLu8gRM,68
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=X8xNBLUhnea97t3qeeZJ2XyUwW_a38YiznXr73j_ppE,950
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.2.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
2069
- vellum_ai-1.7.2.dist-info/METADATA,sha256=KyFKrTqcT-6Pvl5zTeo1EsEP0-uY4WREJPAr8Vdkh4A,5547
2070
- vellum_ai-1.7.2.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
2071
- vellum_ai-1.7.2.dist-info/entry_points.txt,sha256=xVavzAKN4iF_NbmhWOlOkHluka0YLkbN_pFQ9pW3gLI,117
2072
- vellum_ai-1.7.2.dist-info/RECORD,,
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,,