vellum-ai 1.3.5__py3-none-any.whl → 1.3.7__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.
Files changed (25) hide show
  1. vellum/client/README.md +16 -0
  2. vellum/client/core/client_wrapper.py +2 -2
  3. vellum/plugins/vellum_mypy.py +12 -9
  4. vellum/workflows/executable.py +9 -0
  5. vellum/workflows/graph/graph.py +5 -0
  6. vellum/workflows/graph/tests/test_graph.py +17 -0
  7. vellum/workflows/nodes/bases/base.py +2 -3
  8. vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py +9 -2
  9. vellum/workflows/nodes/displayable/tool_calling_node/node.py +2 -0
  10. vellum/workflows/nodes/displayable/tool_calling_node/utils.py +7 -1
  11. vellum/workflows/outputs/base.py +14 -5
  12. vellum/workflows/references/output.py +1 -1
  13. vellum/workflows/utils/names.py +12 -4
  14. vellum/workflows/utils/tests/test_names.py +9 -0
  15. vellum/workflows/workflows/base.py +3 -5
  16. {vellum_ai-1.3.5.dist-info → vellum_ai-1.3.7.dist-info}/METADATA +1 -1
  17. {vellum_ai-1.3.5.dist-info → vellum_ai-1.3.7.dist-info}/RECORD +25 -24
  18. vellum_ee/workflows/display/nodes/tests/test_base_node_display.py +17 -0
  19. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py +1 -1
  20. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_parent_input.py +5 -1
  21. vellum_ee/workflows/display/utils/expressions.py +35 -14
  22. vellum_ee/workflows/display/workflows/base_workflow_display.py +3 -9
  23. {vellum_ai-1.3.5.dist-info → vellum_ai-1.3.7.dist-info}/LICENSE +0 -0
  24. {vellum_ai-1.3.5.dist-info → vellum_ai-1.3.7.dist-info}/WHEEL +0 -0
  25. {vellum_ai-1.3.5.dist-info → vellum_ai-1.3.7.dist-info}/entry_points.txt +0 -0
vellum/client/README.md CHANGED
@@ -232,3 +232,19 @@ client = Vellum(
232
232
  )
233
233
  ```
234
234
 
235
+ ## Contributing
236
+
237
+ While we value open-source contributions to this SDK, this library is generated programmatically.
238
+ Additions made directly to this library would have to be moved over to our generation code,
239
+ otherwise they would be overwritten upon the next generated release. Feel free to open a PR as
240
+ a proof of concept, but know that we will not be able to merge it as-is. We suggest opening
241
+ an issue first to discuss with us!
242
+
243
+ On the other hand, contributions to the README are always very welcome!
244
+ ## Open-Source vs. Paid
245
+
246
+ This repo is available under the [MIT expat license](https://github.com/vellum-ai/vellum-python-sdks/blob/main/LICENSE), except
247
+ for the `ee` directory (which has its [license here](https://github.com/vellum-ai/vellum-python-sdks/blob/main/ee/LICENSE)) if applicable.
248
+
249
+ To learn more, [book a demo](https://www.vellum.ai/landing-pages/request-demo) or see our [pricing page](https://www.vellum.ai/pricing).
250
+
@@ -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.3.5",
30
+ "User-Agent": "vellum-ai/1.3.7",
31
31
  "X-Fern-Language": "Python",
32
32
  "X-Fern-SDK-Name": "vellum-ai",
33
- "X-Fern-SDK-Version": "1.3.5",
33
+ "X-Fern-SDK-Version": "1.3.7",
34
34
  **(self.get_custom_headers() or {}),
35
35
  }
36
36
  if self._api_version is not None:
@@ -20,6 +20,7 @@ from mypy.types import AnyType, CallableType, FunctionLike, Instance, Type as My
20
20
 
21
21
  TypeResolver = Callable[[str, List[MypyType]], MypyType]
22
22
  NODE_ATTRIBUTE_REGEX = r"^[a-z].*$"
23
+ BASE_NODE_FULLNAME = "vellum.workflows.nodes.bases.base.BaseNode"
23
24
 
24
25
  DESCRIPTOR_PATHS: list[tuple[str, str, str]] = [
25
26
  (
@@ -28,12 +29,12 @@ DESCRIPTOR_PATHS: list[tuple[str, str, str]] = [
28
29
  r"^[^_].*$",
29
30
  ),
30
31
  (
31
- "vellum.workflows.nodes.bases.base.BaseNode.ExternalInputs",
32
+ f"{BASE_NODE_FULLNAME}.ExternalInputs",
32
33
  "vellum.workflows.references.external_input.ExternalInputReference",
33
34
  r"^[^_].*$",
34
35
  ),
35
36
  (
36
- "vellum.workflows.nodes.bases.base.BaseNode.Execution",
37
+ f"{BASE_NODE_FULLNAME}.Execution",
37
38
  "vellum.workflows.references.execution_count.ExecutionCountReference",
38
39
  r"^count$",
39
40
  ),
@@ -48,7 +49,7 @@ DESCRIPTOR_PATHS: list[tuple[str, str, str]] = [
48
49
  r"^[^_].*$",
49
50
  ),
50
51
  (
51
- "vellum.workflows.nodes.bases.base.BaseNode",
52
+ BASE_NODE_FULLNAME,
52
53
  "vellum.workflows.references.node.NodeReference",
53
54
  NODE_ATTRIBUTE_REGEX,
54
55
  ),
@@ -163,7 +164,7 @@ class VellumMypyPlugin(Plugin):
163
164
  elif _is_subclass(ctx.cls.info, "vellum.workflows.nodes.displayable.final_output_node.node.FinalOutputNode"):
164
165
  self._dynamic_output_node_class_hook(ctx, "value")
165
166
 
166
- if _is_subclass(ctx.cls.info, "vellum.workflows.nodes.bases.base.BaseNode"):
167
+ if _is_subclass(ctx.cls.info, BASE_NODE_FULLNAME):
167
168
  return self._base_node_class_hook(ctx)
168
169
 
169
170
  if _is_subclass(ctx.cls.info, "vellum.workflows.workflows.base.BaseWorkflow"):
@@ -241,6 +242,9 @@ class VellumMypyPlugin(Plugin):
241
242
  """
242
243
 
243
244
  for key, sym in ctx.cls.info.names.items():
245
+ if ctx.cls.info.fullname == BASE_NODE_FULLNAME:
246
+ continue
247
+
244
248
  if not isinstance(sym.node, Var):
245
249
  continue
246
250
 
@@ -250,6 +254,7 @@ class VellumMypyPlugin(Plugin):
250
254
  type_ = sym.node.type
251
255
  if not type_:
252
256
  continue
257
+
253
258
  sym.node.type = self._get_resolvable_type(
254
259
  lambda fullname, types: ctx.api.named_type(fullname, types), type_
255
260
  )
@@ -301,7 +306,7 @@ class VellumMypyPlugin(Plugin):
301
306
  and isinstance(arg.expr, MemberExpr)
302
307
  and isinstance(arg.expr.expr, NameExpr)
303
308
  and isinstance(arg.expr.expr.node, TypeInfo)
304
- and _is_subclass(arg.expr.expr.node, "vellum.workflows.nodes.bases.base.BaseNode")
309
+ and _is_subclass(arg.expr.expr.node, BASE_NODE_FULLNAME)
305
310
  and arg.expr.name == "Outputs"
306
311
  ):
307
312
  self._calls_with_nested_descriptor_expressions.add(call_expr)
@@ -548,7 +553,7 @@ class VellumMypyPlugin(Plugin):
548
553
  if not isinstance(ctx.default_return_type, Instance):
549
554
  return ctx.default_return_type
550
555
 
551
- if not _is_subclass(ctx.default_return_type.type, "vellum.workflows.nodes.bases.base.BaseNode.Outputs"):
556
+ if not _is_subclass(ctx.default_return_type.type, f"{BASE_NODE_FULLNAME}.Outputs"):
552
557
  return ctx.default_return_type
553
558
 
554
559
  outputs_node = self._get_node_outputs_type_info(ctx)
@@ -677,9 +682,7 @@ class VellumMypyPlugin(Plugin):
677
682
 
678
683
  expr = ctx.context.callee.expr
679
684
  instance = ctx.api.get_expression_type(expr)
680
- if not isinstance(instance, Instance) or not _is_subclass(
681
- instance.type, "vellum.workflows.nodes.bases.base.BaseNode"
682
- ):
685
+ if not isinstance(instance, Instance) or not _is_subclass(instance.type, BASE_NODE_FULLNAME):
683
686
  return None
684
687
 
685
688
  outputs_node = instance.type.names.get("Outputs")
@@ -0,0 +1,9 @@
1
+ from uuid import UUID
2
+ from typing import Dict
3
+
4
+ from vellum.workflows.utils.uuids import uuid4_from_hash
5
+
6
+
7
+ class BaseExecutable:
8
+ __id__: UUID = uuid4_from_hash(__qualname__)
9
+ __output_ids__: Dict[str, UUID] = {}
@@ -96,6 +96,11 @@ class Graph:
96
96
  def from_edge(edge: Edge) -> "Graph":
97
97
  return Graph(entrypoints={edge.from_port}, edges=[edge], terminals={port for port in edge.to_node.Ports})
98
98
 
99
+ @staticmethod
100
+ def empty() -> "Graph":
101
+ """Create an empty graph with no entrypoints, edges, or terminals."""
102
+ return Graph(entrypoints=set(), edges=[], terminals=set())
103
+
99
104
  def __rshift__(self, other: GraphTarget) -> "Graph":
100
105
  if not self._edges and not self._entrypoints:
101
106
  raise ValueError("Graph instance can only create new edges from nodes within existing edges")
@@ -4,6 +4,23 @@ from vellum.workflows.nodes.bases.base import BaseNode
4
4
  from vellum.workflows.ports.port import Port
5
5
 
6
6
 
7
+ def test_graph__empty():
8
+ # WHEN we create an empty graph
9
+ graph = Graph.empty()
10
+
11
+ # THEN the graph has no entrypoints
12
+ assert len(list(graph.entrypoints)) == 0
13
+
14
+ # AND no nodes
15
+ assert len(list(graph.nodes)) == 0
16
+
17
+ # AND no edges
18
+ assert len(list(graph.edges)) == 0
19
+
20
+ # AND string representation indicates empty graph
21
+ assert str(graph) == "Graph(empty)"
22
+
23
+
7
24
  def test_graph__from_node():
8
25
  # GIVEN a node
9
26
  class MyNode(BaseNode):
@@ -13,6 +13,7 @@ from vellum.workflows.descriptors.utils import is_unresolved, resolve_value
13
13
  from vellum.workflows.errors.types import WorkflowErrorCode
14
14
  from vellum.workflows.events.node import NodeExecutionStreamingEvent
15
15
  from vellum.workflows.exceptions import NodeException
16
+ from vellum.workflows.executable import BaseExecutable
16
17
  from vellum.workflows.graph import Graph
17
18
  from vellum.workflows.graph.graph import GraphTarget
18
19
  from vellum.workflows.inputs.base import BaseInputs
@@ -260,9 +261,7 @@ class _BaseNodeExecutionMeta(type):
260
261
  NodeRunResponse = Union[BaseOutputs, Iterator[BaseOutput]]
261
262
 
262
263
 
263
- class BaseNode(Generic[StateType], ABC, metaclass=BaseNodeMeta):
264
- __id__: UUID = uuid4_from_hash(__qualname__)
265
- __output_ids__: Dict[str, UUID] = {}
264
+ class BaseNode(Generic[StateType], ABC, BaseExecutable, metaclass=BaseNodeMeta):
266
265
  state: StateType
267
266
  _context: WorkflowContext
268
267
  _inputs: MappingProxyType[NodeReference, Any]
@@ -101,6 +101,7 @@ class BaseInlinePromptNode(BasePromptNode[StateType], Generic[StateType]):
101
101
  request_options = self.request_options or RequestOptions()
102
102
 
103
103
  processed_parameters = self.process_parameters(self.parameters)
104
+ processed_blocks = self.process_blocks(self.blocks)
104
105
 
105
106
  request_options["additional_body_parameters"] = {
106
107
  "execution_context": execution_context.model_dump(mode="json"),
@@ -139,7 +140,7 @@ class BaseInlinePromptNode(BasePromptNode[StateType], Generic[StateType]):
139
140
  input_values=input_values,
140
141
  input_variables=input_variables,
141
142
  parameters=processed_parameters,
142
- blocks=self.blocks,
143
+ blocks=processed_blocks,
143
144
  settings=self.settings,
144
145
  functions=normalized_functions,
145
146
  expand_meta=self.expand_meta,
@@ -152,7 +153,7 @@ class BaseInlinePromptNode(BasePromptNode[StateType], Generic[StateType]):
152
153
  input_values=input_values,
153
154
  input_variables=input_variables,
154
155
  parameters=processed_parameters,
155
- blocks=self.blocks,
156
+ blocks=processed_blocks,
156
157
  settings=self.settings,
157
158
  functions=normalized_functions,
158
159
  expand_meta=self.expand_meta,
@@ -310,3 +311,9 @@ class BaseInlinePromptNode(BasePromptNode[StateType], Generic[StateType]):
310
311
  processed_custom_params = normalize_json(parameters.custom_parameters)
311
312
 
312
313
  return parameters.model_copy(update={"custom_parameters": processed_custom_params})
314
+
315
+ def process_blocks(self, blocks: List[PromptBlock]) -> List[PromptBlock]:
316
+ """
317
+ Override this method to process the blocks before they are executed.
318
+ """
319
+ return blocks
@@ -140,6 +140,7 @@ class ToolCallingNode(BaseNode[StateType], Generic[StateType]):
140
140
  def _build_graph(self) -> None:
141
141
  # Get the process_parameters method if it exists on this class
142
142
  process_parameters_method = getattr(self.__class__, "process_parameters", None)
143
+ process_blocks_method = getattr(self.__class__, "process_blocks", None)
143
144
 
144
145
  self.tool_prompt_node = create_tool_prompt_node(
145
146
  ml_model=self.ml_model,
@@ -149,6 +150,7 @@ class ToolCallingNode(BaseNode[StateType], Generic[StateType]):
149
150
  parameters=self.parameters,
150
151
  max_prompt_iterations=self.max_prompt_iterations,
151
152
  process_parameters_method=process_parameters_method,
153
+ process_blocks_method=process_blocks_method,
152
154
  )
153
155
 
154
156
  # Create the router node (handles routing logic only)
@@ -14,6 +14,7 @@ from vellum.client.types.prompt_output import PromptOutput
14
14
  from vellum.client.types.prompt_parameters import PromptParameters
15
15
  from vellum.client.types.string_chat_message_content import StringChatMessageContent
16
16
  from vellum.client.types.variable_prompt_block import VariablePromptBlock
17
+ from vellum.workflows.descriptors.base import BaseDescriptor
17
18
  from vellum.workflows.errors.types import WorkflowErrorCode
18
19
  from vellum.workflows.exceptions import NodeException
19
20
  from vellum.workflows.expressions.concat import ConcatExpression
@@ -330,6 +331,7 @@ def create_tool_prompt_node(
330
331
  parameters: PromptParameters,
331
332
  max_prompt_iterations: Optional[int] = None,
332
333
  process_parameters_method: Optional[Callable] = None,
334
+ process_blocks_method: Optional[Callable] = None,
333
335
  ) -> Type[ToolPromptNode]:
334
336
  if functions and len(functions) > 0:
335
337
  prompt_functions: List[Union[Tool, FunctionDefinition]] = []
@@ -400,6 +402,7 @@ def create_tool_prompt_node(
400
402
  "parameters": parameters,
401
403
  "max_prompt_iterations": max_prompt_iterations,
402
404
  **({"process_parameters": process_parameters_method} if process_parameters_method is not None else {}),
405
+ **({"process_blocks": process_blocks_method} if process_blocks_method is not None else {}),
403
406
  "__module__": __name__,
404
407
  },
405
408
  ),
@@ -529,7 +532,10 @@ def create_function_node(
529
532
  inputs = getattr(func, "__vellum_inputs__", {})
530
533
  if inputs:
531
534
  for param_name, param_ref in inputs.items():
532
- resolved_value = param_ref.resolve(self.state)
535
+ if isinstance(param_ref, BaseDescriptor):
536
+ resolved_value = param_ref.resolve(self.state)
537
+ else:
538
+ resolved_value = param_ref
533
539
  merged_kwargs[param_name] = resolved_value
534
540
 
535
541
  return func(**merged_kwargs)
@@ -1,6 +1,6 @@
1
1
  from dataclasses import field
2
2
  import inspect
3
- from typing import Any, Generic, Iterator, Set, Tuple, Type, TypeVar, Union, cast
3
+ from typing import Any, Dict, Generic, Iterator, Set, Tuple, Type, TypeVar, Union, cast
4
4
  from typing_extensions import dataclass_transform
5
5
 
6
6
  from pydantic import GetCoreSchemaHandler
@@ -10,6 +10,7 @@ from vellum.workflows.constants import undefined
10
10
  from vellum.workflows.descriptors.base import BaseDescriptor
11
11
  from vellum.workflows.errors.types import WorkflowErrorCode
12
12
  from vellum.workflows.exceptions import NodeException
13
+ from vellum.workflows.executable import BaseExecutable
13
14
  from vellum.workflows.references.output import OutputReference
14
15
  from vellum.workflows.types.generics import is_node_instance
15
16
  from vellum.workflows.types.utils import get_class_attr_names, infer_types
@@ -99,6 +100,10 @@ class BaseOutput(Generic[_Delta, _Accumulated]):
99
100
 
100
101
  @dataclass_transform(kw_only_default=True)
101
102
  class _BaseOutputsMeta(type):
103
+ def __new__(cls, name: str, bases: Tuple[Type, ...], dct: Dict[str, Any]) -> Any:
104
+ dct["__parent_class__"] = type(None)
105
+ return super().__new__(cls, name, bases, dct)
106
+
102
107
  def __eq__(cls, other: Any) -> bool:
103
108
  """
104
109
  We need to include custom eq logic to prevent infinite loops during ipython reloading.
@@ -119,7 +124,13 @@ class _BaseOutputsMeta(type):
119
124
  if self_outputs_class.__parent_class__ is None or other_outputs_class.__parent_class__ is None:
120
125
  return super().__eq__(other)
121
126
 
122
- return self_outputs_class.__parent_class__.__qualname__ == other_outputs_class.__parent_class__.__qualname__
127
+ if self_outputs_class.__parent_class__ is type(None) or other_outputs_class.__parent_class__ is type(None):
128
+ return super().__eq__(other)
129
+
130
+ return (
131
+ self_outputs_class.__parent_class__.__qualname__ == other_outputs_class.__parent_class__.__qualname__
132
+ and self_outputs_class.__parent_class__.__module__ == other_outputs_class.__parent_class__.__module__
133
+ )
123
134
 
124
135
  def __setattr__(cls, name: str, value: Any) -> None:
125
136
  if isinstance(value, OutputReference):
@@ -183,9 +194,7 @@ class _BaseOutputsMeta(type):
183
194
 
184
195
 
185
196
  class BaseOutputs(metaclass=_BaseOutputsMeta):
186
- # TODO: Uncomment once we figure out why this causes a failure in `infer_types`
187
- # __parent_class__: Type[Union["BaseNode", "BaseWorkflow"]] = field(init=False)
188
- __parent_class__: Type = field(init=False)
197
+ __parent_class__: Type[BaseExecutable] = field(init=False)
189
198
 
190
199
  def __init__(self, **kwargs: Any) -> None:
191
200
  declared_fields = {descriptor.name for descriptor in self.__class__}
@@ -76,7 +76,7 @@ class OutputReference(BaseDescriptor[_OutputType], Generic[_OutputType]):
76
76
  def __eq__(self, other: object) -> bool:
77
77
  if not isinstance(other, type(self)):
78
78
  return False
79
- return super().__eq__(other) and id(self._outputs_class) == id(other._outputs_class)
79
+ return super().__eq__(other) and self._outputs_class == other._outputs_class
80
80
 
81
81
  def __hash__(self) -> int:
82
82
  return hash((self._outputs_class, self._name))
@@ -2,11 +2,19 @@ import re
2
2
 
3
3
 
4
4
  def pascal_to_title_case(pascal_str: str) -> str:
5
- # Insert space before each capital letter (except the first one)
6
- title_case_str = re.sub(r"(?<!^)(?=[A-Z])", " ", pascal_str)
5
+ title_case_str = re.sub(r"(?<=[a-z])(?=[A-Z])|(?<=[A-Z])(?=[A-Z][a-z])", " ", pascal_str)
7
6
 
8
- # Return the result in title case
9
- return title_case_str.title()
7
+ words = title_case_str.split()
8
+ result_words = []
9
+
10
+ for word in words:
11
+ if word.isupper():
12
+ result_words.append(word)
13
+ # Otherwise, apply title case
14
+ else:
15
+ result_words.append(word.capitalize())
16
+
17
+ return " ".join(result_words)
10
18
 
11
19
 
12
20
  def snake_to_title_case(snake_str: str) -> str:
@@ -8,6 +8,15 @@ from vellum.workflows.utils.names import pascal_to_title_case
8
8
  [
9
9
  ("MyPascalCaseString", "My Pascal Case String"),
10
10
  ("AnotherPascalCaseString", "Another Pascal Case String"),
11
+ ("FetchDeploymentScheme", "Fetch Deployment Scheme"),
12
+ ("CheckDeploymentExists", "Check Deployment Exists"),
13
+ ("APINode", "API Node"),
14
+ ("HTTPSConnection", "HTTPS Connection"),
15
+ ("XMLParser", "XML Parser"),
16
+ ("SimpleWord", "Simple Word"),
17
+ ("A", "A"),
18
+ ("AB", "AB"),
19
+ ("ABCDef", "ABC Def"),
11
20
  ],
12
21
  )
13
22
  def test_pascal_to_title_case(input_str, expected):
@@ -62,6 +62,7 @@ from vellum.workflows.events.workflow import (
62
62
  WorkflowExecutionStreamingBody,
63
63
  WorkflowExecutionStreamingEvent,
64
64
  )
65
+ from vellum.workflows.executable import BaseExecutable
65
66
  from vellum.workflows.graph import Graph
66
67
  from vellum.workflows.inputs.base import BaseInputs
67
68
  from vellum.workflows.nodes.bases import BaseNode
@@ -200,8 +201,7 @@ class _BaseWorkflowMeta(type):
200
201
  if inputs_class is not BaseInputs and inputs_class.__parent_class__ is type(None):
201
202
  inputs_class.__parent_class__ = workflow_class
202
203
 
203
- # TODO: Uncomment this once we figure out why it's causing the ipython reload test to fail
204
- # workflow_class.Outputs.__parent_class__ = workflow_class
204
+ workflow_class.Outputs.__parent_class__ = workflow_class
205
205
  workflow_class.__output_ids__ = {
206
206
  ref.name: uuid4_from_hash(f"{workflow_class.__id__}|id|{ref.name}") for ref in workflow_class.Outputs
207
207
  }
@@ -212,9 +212,7 @@ class _BaseWorkflowMeta(type):
212
212
  GraphAttribute = Union[Type[BaseNode], Graph, Set[Type[BaseNode]], Set[Graph]]
213
213
 
214
214
 
215
- class BaseWorkflow(Generic[InputsType, StateType], metaclass=_BaseWorkflowMeta):
216
- __id__: UUID = uuid4_from_hash(__qualname__)
217
- __output_ids__: Dict[str, UUID] = {}
215
+ class BaseWorkflow(Generic[InputsType, StateType], BaseExecutable, metaclass=_BaseWorkflowMeta):
218
216
  graph: ClassVar[GraphAttribute]
219
217
  unused_graphs: ClassVar[Set[GraphAttribute]] # nodes or graphs that are defined but not used in the graph
220
218
  emitters: List[BaseWorkflowEmitter]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vellum-ai
3
- Version: 1.3.5
3
+ Version: 1.3.7
4
4
  Summary:
5
5
  License: MIT
6
6
  Requires-Python: >=3.9,<4.0
@@ -33,7 +33,7 @@ vellum_ee/workflows/display/nodes/__init__.py,sha256=jI1aPBQf8DkmrYoZ4O-wR1duqZB
33
33
  vellum_ee/workflows/display/nodes/base_node_display.py,sha256=98vszulLRvYz0kAh7ZEOeWOqzMtlpnOZM2lAViOUieA,18393
34
34
  vellum_ee/workflows/display/nodes/get_node_display_class.py,sha256=jI_kUi9LnNLDpY63QtlC4TfN8P571VN4LpzH0I1ZtLk,1149
35
35
  vellum_ee/workflows/display/nodes/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
- vellum_ee/workflows/display/nodes/tests/test_base_node_display.py,sha256=wBoCqULS4XO3s9Vwhd9v4g10opfBFqeZgRqB8CoFz0c,3015
36
+ vellum_ee/workflows/display/nodes/tests/test_base_node_display.py,sha256=Cg5Ker3amAn2wraeNW4t_puvIZdvRB-P8XIL-p4GGL0,3571
37
37
  vellum_ee/workflows/display/nodes/types.py,sha256=St1BB6no528OyELGiyRabWao0GGw6mLhstQAvEACbGk,247
38
38
  vellum_ee/workflows/display/nodes/utils.py,sha256=sloya5TpXsnot1HURc9L51INwflRqUzHxRVnCS9Cd-4,973
39
39
  vellum_ee/workflows/display/nodes/vellum/__init__.py,sha256=nUIgH2s0-7IbQRNrBhLPyRNe8YIrx3Yo9HeeW-aXXFk,1668
@@ -81,7 +81,7 @@ vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attr
81
81
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py,sha256=O1CIKMmRTaMaT3IhjwCAiMz1ZThPg9lAUbSiZkx_E8c,6321
82
82
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py,sha256=fPXcX-tWQ0UMuEyOFAylgi7pWiE7lZWk9vrShlTExik,40053
83
83
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py,sha256=FLvcD8eoABHUPv08oSpIp_P-65sw2gl4whMXEJJj4f8,6785
84
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py,sha256=ygNirKPjErhjTkDIgFZdaLrsvxDmUEionlmYFMJju3w,16338
84
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py,sha256=D_ZGMOgr5Ek33ZQagv08b8up1U0Lc0dCgAjnO8ZEpzQ,16336
85
85
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py,sha256=arl-tho6f0qstUM2ejONEO4ru_6TxCPbni3FS-UZouQ,30108
86
86
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py,sha256=-BiFVw3JUx_79isQNgAtZB2362oByRcuAuUVK9uzCJI,54204
87
87
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_default_state_serialization.py,sha256=E1ww97BFoGbnRkxf84TScat5NQhP8nLVrdaOlpGnSKU,8615
@@ -100,7 +100,7 @@ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_nod
100
100
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_composio_serialization.py,sha256=oVXCjkU0G56QJmqnd_xIwF3D9bhJwALFibM2wmRhwUk,3739
101
101
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_serialization.py,sha256=Sg82qV5NCzQDy-RD90hA6QaHgFHOq6ESNkbWXygsnNw,26367
102
102
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_mcp_serialization.py,sha256=QhQbijeCnFeX1i3SMjHJg2WVAEt5JEO3dhFRv-mofdA,2458
103
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_parent_input.py,sha256=HMMa4liBACtL7vU2b-9Ui8Oltyxxb5dbAf-CziLGCes,4284
103
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_parent_input.py,sha256=__LX4cuzbyZp_1wc-SI8X_J0tnhOkCEmRVUWLKI5aQM,4578
104
104
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_serialization.py,sha256=cKaxme5vUIvKa8aBU7xdeFxXF9wVZ5fW3T5Ie5vToU0,10152
105
105
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_workflow_deployment_serialization.py,sha256=XIZZr5POo2NLn2uEWm9EC3rejeBMoO4X-JtzTH6mvp4,4074
106
106
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py,sha256=pLCyMScV88DTBXRH7jXaXOEA1GBq8NIipCUFwIAWnwI,2771
@@ -113,7 +113,7 @@ vellum_ee/workflows/display/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeR
113
113
  vellum_ee/workflows/display/utils/auto_layout.py,sha256=f4GiLn_LazweupfqTpubcdtdfE_vrOcmZudSsnYIY9E,3906
114
114
  vellum_ee/workflows/display/utils/events.py,sha256=MEG2BT6GgAzkbv1dMaFpov5OShtaAZeAb1-g3xDFsAM,1826
115
115
  vellum_ee/workflows/display/utils/exceptions.py,sha256=LSwwxCYNxFkf5XMUcFkaZKpQ13OSrI7y_bpEUwbKVk0,169
116
- vellum_ee/workflows/display/utils/expressions.py,sha256=ci6vOzfCwqVrSRI9A-HR7t4bz_reuS2kzr71SHYIloI,19118
116
+ vellum_ee/workflows/display/utils/expressions.py,sha256=80TcSWhT249cvT_NRobwelWCLWKgeFQEpXCvjFq0fwY,19743
117
117
  vellum_ee/workflows/display/utils/registry.py,sha256=1qXiBTdsnro6FeCX0FGBEK7CIf6wa--Jt50iZ_nEp_M,3460
118
118
  vellum_ee/workflows/display/utils/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
119
119
  vellum_ee/workflows/display/utils/tests/test_auto_layout.py,sha256=vfXI769418s9vda5Gb5NFBH747WMOwSgHRXeLCTLVm8,2356
@@ -121,7 +121,7 @@ vellum_ee/workflows/display/utils/tests/test_events.py,sha256=Qze6wEmFJx23_sKQhX
121
121
  vellum_ee/workflows/display/utils/vellum.py,sha256=sZwU0KdmZZTKWW62SyxJTl2tC8tN6p_BpZ-lDoinV-U,5670
122
122
  vellum_ee/workflows/display/vellum.py,sha256=J2mdJZ1sdLW535DDUkq_Vm8Z572vhuxHxVZF9deKSdk,391
123
123
  vellum_ee/workflows/display/workflows/__init__.py,sha256=JTB9ObEV3l4gGGdtfBHwVJtTTKC22uj-a-XjTVwXCyA,148
124
- vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256=5PCZY37qMA3z1Qpu35Ot0koF5-iH4XVctlLzEMJ26OQ,43991
124
+ vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256=HEwhGlQ6AllU_SpGSVCYgRc0RXev4iuHxXX3Rl18Xzs,43674
125
125
  vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py,sha256=gxz76AeCqgAZ9D2lZeTiZzxY9eMgn3qOSfVgiqYcOh8,2028
126
126
  vellum_ee/workflows/display/workflows/tests/test_workflow_display.py,sha256=pb7BTH-ivRnya1LQU3j-MApWk_m8POpPNOdD0oEK82A,37847
127
127
  vellum_ee/workflows/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -151,11 +151,11 @@ vellum_ee/workflows/tests/test_serialize_module.py,sha256=lk-4dVnG2HcxxywBXxDR1i
151
151
  vellum_ee/workflows/tests/test_server.py,sha256=dXFBraU99Y6cKp2aBhLFXQTScSRcE9WaWjo1z9piqdU,23344
152
152
  vellum_ee/workflows/tests/test_virtual_files.py,sha256=TJEcMR0v2S8CkloXNmCHA0QW0K6pYNGaIjraJz7sFvY,2762
153
153
  vellum/__init__.py,sha256=lv4OTbPgTegugVOpRy5xJPPwMvC1Zqrg4oFMEwY1KSg,47428
154
- vellum/client/README.md,sha256=b6XKeYBBbhQx0v1sHWfM0gIJeJhUFF-aqL2ig7ADa08,5564
154
+ vellum/client/README.md,sha256=flqu57ubZNTfpq60CdLtJC9gp4WEkyjb_n_eZ4OYf9w,6497
155
155
  vellum/client/__init__.py,sha256=T5Ht_w-Mk_9nzGqdadhQB8V20M0vYj7am06ut0A3P1o,73401
156
156
  vellum/client/core/__init__.py,sha256=lTcqUPXcx4112yLDd70RAPeqq6tu3eFMe1pKOqkW9JQ,1562
157
157
  vellum/client/core/api_error.py,sha256=44vPoTyWN59gonCIZMdzw7M1uspygiLnr3GNFOoVL2Q,614
158
- vellum/client/core/client_wrapper.py,sha256=Mh9pKr9Xxrby4VuKOk1M3W1PdfGhP8jsj32r0WIAdN8,2840
158
+ vellum/client/core/client_wrapper.py,sha256=KMoMI878fMQf0TrjYh3YzBK3pntYQnSutU6ad-cuzsc,2840
159
159
  vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
160
160
  vellum/client/core/file.py,sha256=d4NNbX8XvXP32z8KpK2Xovv33nFfruIrpz0QWxlgpZk,2663
161
161
  vellum/client/core/force_multipart.py,sha256=awxh5MtcRYe74ehY8U76jzv6fYM_w_D3Rur7KQQzSDk,429
@@ -950,7 +950,7 @@ vellum/plugins/pydantic.py,sha256=SamPlRZ8V9kuxEfMkOPKjhMMLa5Q3wYJ3Z-F_IfKtvA,39
950
950
  vellum/plugins/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
951
951
  vellum/plugins/tests/test_pydantic.py,sha256=S6bLqs3Y5DGA012QV_7f6hk4e6Bz-iJ9py9DEKuo4fM,746
952
952
  vellum/plugins/utils.py,sha256=cPmxE9R2CK1bki2jKE8rB-G9zMf2pzHjSPDHFPXwd3Q,878
953
- vellum/plugins/vellum_mypy.py,sha256=hfjC2rIxNdQuJa6fIN4PDgODnQ3YaUszyaV2eNbLJlE,27952
953
+ vellum/plugins/vellum_mypy.py,sha256=awSjop_Vn7VRCQZCy5rNUMq8n_ueNjGJ0wHVN-rTVJY,27916
954
954
  vellum/prompts/__init__.py,sha256=kn-btvQOMNnnBuyQiUpie48_VBJAk7tFFU-ul5dwK60,107
955
955
  vellum/prompts/blocks/__init__.py,sha256=Zwvncjd8sUCPmT-8pFpgLYsKJl0xB6td1GTQzjV9hYA,108
956
956
  vellum/prompts/blocks/compilation.py,sha256=mCGfqJXcKMkv565Ye5y9MsPdVAmkCGOnqQBRa3nJVg8,10754
@@ -1740,6 +1740,7 @@ vellum/workflows/events/tests/test_event.py,sha256=V26TNmbo2aL4sDvcY3nPxCWgcoS4e
1740
1740
  vellum/workflows/events/types.py,sha256=mVrqAH9Hs9SpXm08Hcxdyap_ImQPwGsxRr56rSNMP34,5043
1741
1741
  vellum/workflows/events/workflow.py,sha256=kLSWFXiDZH0TELWoDjQ_kHVomFnw8MVVUPDGIzgyosw,8997
1742
1742
  vellum/workflows/exceptions.py,sha256=NiBiR3ggfmPxBVqD-H1SqmjI-7mIn0EStSN1BqApvCM,1213
1743
+ vellum/workflows/executable.py,sha256=um-gLJMVYfGJwGJfZIPlCRHhHIYm6pn8PUEfeqrNx5k,218
1743
1744
  vellum/workflows/expressions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1744
1745
  vellum/workflows/expressions/accessor.py,sha256=3lu1-_-dBfZdJvtX-q66jbmRAZtqIfdsh_3_JNuzg1E,4462
1745
1746
  vellum/workflows/expressions/add.py,sha256=Rr1O83nksL5Z0kam4eaQOokvDrEwlUg7LqWnXzGUW40,1226
@@ -1785,9 +1786,9 @@ vellum/workflows/expressions/tests/test_length.py,sha256=pQA1tYSwqxE6euclboY024N
1785
1786
  vellum/workflows/expressions/tests/test_minus.py,sha256=pq7dvdRGNhSSn95LGNzRErsYUsFk5SpOKHDcSR5QToc,1632
1786
1787
  vellum/workflows/expressions/tests/test_parse_json.py,sha256=zpB_qE5_EwWQL7ULQUJm0o1PRSfWZdAqZNW6Ah13oJE,1059
1787
1788
  vellum/workflows/graph/__init__.py,sha256=3sHlay5d_-uD7j3QJXiGl0WHFZZ_QScRvgyDhN2GhHY,74
1788
- vellum/workflows/graph/graph.py,sha256=kUKNMcxw9jtcnHbLdMPgY7t-lxIml6HbFy1uFkgPcRw,11088
1789
+ vellum/workflows/graph/graph.py,sha256=vkpteMc2a61IFGHlrA50J4ntVj6m3agcyWrXGQEbjHc,11280
1789
1790
  vellum/workflows/graph/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1790
- vellum/workflows/graph/tests/test_graph.py,sha256=04FUSFk38fRwO7NZANaS34WkDowqQ21cLwamRSJlel8,15045
1791
+ vellum/workflows/graph/tests/test_graph.py,sha256=0Pov0sCsxjzUDL9wy7xy9jFD-F2GsMJnZVEVFXzQGdM,15433
1791
1792
  vellum/workflows/inputs/__init__.py,sha256=AbFEteIYEvCb14fM3EK7bhM-40-6s494rSlIhQ4Dsss,62
1792
1793
  vellum/workflows/inputs/base.py,sha256=w3owT5B3rLBmIj-v-jL2l-HD4yd3hXK9RmHVd557BpA,5126
1793
1794
  vellum/workflows/inputs/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -1799,7 +1800,7 @@ vellum/workflows/integrations/tests/test_mcp_service.py,sha256=q_DYrDkIqI4sQBNgI
1799
1800
  vellum/workflows/logging.py,sha256=_a217XogktV4Ncz6xKFz7WfYmZAzkfVRVuC0rWob8ls,437
1800
1801
  vellum/workflows/nodes/__init__.py,sha256=zymtc3_iW2rFmMR-sayTLuN6ZsAw8VnJweWPsjQk2-Q,1197
1801
1802
  vellum/workflows/nodes/bases/__init__.py,sha256=cniHuz_RXdJ4TQgD8CBzoiKDiPxg62ErdVpCbWICX64,58
1802
- vellum/workflows/nodes/bases/base.py,sha256=424pCSFZtXqMpAYX01nQCP3Ej2s16_ynWY3VtxUwTdo,20497
1803
+ vellum/workflows/nodes/bases/base.py,sha256=i4tuPo_KyFI1ZJh__AI-oxRkDGch9pNTmOqt69HTcE0,20478
1803
1804
  vellum/workflows/nodes/bases/base_adornment_node.py,sha256=hrgzuTetM4ynPd9YGHoK8Vwwn4XITi3aZZ_OCnQrq4Y,3433
1804
1805
  vellum/workflows/nodes/bases/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1805
1806
  vellum/workflows/nodes/bases/tests/test_base_adornment_node.py,sha256=fXZI9KqpS4XMBrBnIEkK3foHaBVvyHwYcQWWDKay7ic,1148
@@ -1839,7 +1840,7 @@ vellum/workflows/nodes/displayable/bases/api_node/tests/test_node.py,sha256=5C59
1839
1840
  vellum/workflows/nodes/displayable/bases/base_prompt_node/__init__.py,sha256=Org3xTvgp1pA0uUXFfnJr29D3HzCey2lEdYF4zbIUgo,70
1840
1841
  vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py,sha256=ea20icDM1HB942wkH-XtXNSNCBDcjeOiN3vowkHL4fs,4477
1841
1842
  vellum/workflows/nodes/displayable/bases/inline_prompt_node/__init__.py,sha256=Hl35IAoepRpE-j4cALaXVJIYTYOF3qszyVbxTj4kS1s,82
1842
- vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py,sha256=wtJjaV0tJ5svO0shxFA-lInDQB25wfv24VUvAOYLOZ8,13793
1843
+ vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py,sha256=qxABS2tl7gXfU350-0geBMoL25QrgyqR6-vhUAQt4Qk,14065
1843
1844
  vellum/workflows/nodes/displayable/bases/inline_prompt_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1844
1845
  vellum/workflows/nodes/displayable/bases/inline_prompt_node/tests/test_inline_prompt_node.py,sha256=Hk_u2IxLIeeqL_s0RTgoyL5QGYwY9VllKT8z5_JHiDU,24956
1845
1846
  vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py,sha256=0a40fkkZkFMmZN0CsWf6EP_y1H6x36EGa3WcfVNyOsM,9797
@@ -1893,13 +1894,13 @@ vellum/workflows/nodes/displayable/tests/test_search_node_error_handling.py,sha2
1893
1894
  vellum/workflows/nodes/displayable/tests/test_search_node_wth_text_output.py,sha256=VepO5z1277c1y5N6LLIC31nnWD1aak2m5oPFplfJHHs,6935
1894
1895
  vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py,sha256=Bjv-wZyFgNaVZb9KEMMZd9lFoLzbPEPjEMpANizMZw4,2413
1895
1896
  vellum/workflows/nodes/displayable/tool_calling_node/__init__.py,sha256=3n0-ysmFKsr40CVxPthc0rfJgqVJeZuUEsCmYudLVRg,117
1896
- vellum/workflows/nodes/displayable/tool_calling_node/node.py,sha256=KxKU8JWFr-XUdwYelEtUTfAh3UaN3FTm2wK-nioXu9U,8065
1897
+ vellum/workflows/nodes/displayable/tool_calling_node/node.py,sha256=J4RNOggTx5nzovC0354SPGV-NkRpYnV51PMTYQ7aIQ8,8202
1897
1898
  vellum/workflows/nodes/displayable/tool_calling_node/state.py,sha256=CcBVb_YtwfSSka4ze678k6-qwmzMSfjfVP8_Y95feSo,302
1898
1899
  vellum/workflows/nodes/displayable/tool_calling_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1899
1900
  vellum/workflows/nodes/displayable/tool_calling_node/tests/test_composio_service.py,sha256=in1fbEz5x1tx3uKv9YXdvOncsHucNL8Ro6Go7lBuuOQ,8962
1900
1901
  vellum/workflows/nodes/displayable/tool_calling_node/tests/test_node.py,sha256=GZoeybB9uM7ai8sBLAtUMHrMVgh-WrJDWrKZci6feDs,11892
1901
1902
  vellum/workflows/nodes/displayable/tool_calling_node/tests/test_utils.py,sha256=SIu5GCj4tIE4fz-cAcdULtQfqZIhrcc3Doo6TWLXBws,8804
1902
- vellum/workflows/nodes/displayable/tool_calling_node/utils.py,sha256=VC0TenXfktfWHd4ZYQFqiXaZvkhizLJFIK3nQvKoVG0,23780
1903
+ vellum/workflows/nodes/displayable/tool_calling_node/utils.py,sha256=c0fJA-de3yJKGTzKfjyZOkbVhIndSAhZqBZp_DpU1fg,24158
1903
1904
  vellum/workflows/nodes/displayable/web_search_node/__init__.py,sha256=8FOnEP-n-U68cvxTlJW9wphIAGHq5aqjzLM-DoSSXnU,61
1904
1905
  vellum/workflows/nodes/displayable/web_search_node/node.py,sha256=NQYux2bOtuBF5E4tn-fXi5y3btURPRrNqMSM9MAZYI4,5091
1905
1906
  vellum/workflows/nodes/displayable/web_search_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -1914,7 +1915,7 @@ vellum/workflows/nodes/tests/test_mocks.py,sha256=mfPvrs75PKcsNsbJLQAN6PDFoVqs9T
1914
1915
  vellum/workflows/nodes/tests/test_utils.py,sha256=BUugAHx2C9YuCwTlsTXV1Glxca0kW3St6T9o_QFatSU,5649
1915
1916
  vellum/workflows/nodes/utils.py,sha256=wCvf8K5qruT5GwtvnHcQ-LMllktTD8aaFmAGpKQy--c,10720
1916
1917
  vellum/workflows/outputs/__init__.py,sha256=AyZ4pRh_ACQIGvkf0byJO46EDnSix1ZCAXfvh-ms1QE,94
1917
- vellum/workflows/outputs/base.py,sha256=XLt2WnjOhHBC0tT4-1FIUHLVdI1J5NXME6UZxKCKwOI,9741
1918
+ vellum/workflows/outputs/base.py,sha256=zy02zr9DmG3j7Xp3Q8xiOiXFF_c7uNh76jf2LiMS-qE,10132
1918
1919
  vellum/workflows/ports/__init__.py,sha256=bZuMt-R7z5bKwpu4uPW7LlJeePOQWmCcDSXe5frUY5g,101
1919
1920
  vellum/workflows/ports/node_ports.py,sha256=SM9uLAaoaE1HwR-Uqwf2v5zZK5iFnphKs6mE5Ls7ldE,2877
1920
1921
  vellum/workflows/ports/port.py,sha256=PYhmzEHgJyjUjSFkPIQ38cNIKpcXrhYiZlj7nZC5yCk,3989
@@ -1927,7 +1928,7 @@ vellum/workflows/references/external_input.py,sha256=c_4SojTpykCSbGS1Pjmx9FfquyY
1927
1928
  vellum/workflows/references/input.py,sha256=3INu-TLTi4dziWmva6LO3WvgDlPzsjayUx61cVvqLJA,325
1928
1929
  vellum/workflows/references/lazy.py,sha256=jgUYmgt-yAybzPf_R-74MzdU8VuNwMYI8EQqrj9lVR0,2948
1929
1930
  vellum/workflows/references/node.py,sha256=LP854wDVs-9I_aZ7-nkbwXqL2H7W2_3LED2e9FixNS8,1418
1930
- vellum/workflows/references/output.py,sha256=utYoYPVfsPCTFPXcAc0zTVn2aZcFwL_-y1_WLiKMhHA,3329
1931
+ vellum/workflows/references/output.py,sha256=qVa3QmlOyJhyIMOHwOmi1RgHPAOryhdPr2DRj97aEvU,3321
1931
1932
  vellum/workflows/references/state_value.py,sha256=bInUF0A3Pt4-zhA0f6LdSuyv8tz7n5QRkHAEn4gsmqI,711
1932
1933
  vellum/workflows/references/tests/test_lazy.py,sha256=0s50-LizMTlSTBQahpK0fg_xqCucA8YTp6QmIMqPvMk,919
1933
1934
  vellum/workflows/references/vellum_secret.py,sha256=Od4d19a5yletWMqNfJR5d_mZQUkVcFzj29mE-T9J7yE,480
@@ -1964,11 +1965,11 @@ vellum/workflows/types/utils.py,sha256=mTctHITBybpt4855x32oCKALBEcMNLn-9cCmfEKgJ
1964
1965
  vellum/workflows/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1965
1966
  vellum/workflows/utils/functions.py,sha256=6WRRMb_XbxtvhUKOJq5ZChy0KKvlBaQCBiPhvecXT7I,10029
1966
1967
  vellum/workflows/utils/hmac.py,sha256=JJCczc6pyV6DuE1Oa0QVfYPUN_of3zEYmGFib3OZnrE,1135
1967
- vellum/workflows/utils/names.py,sha256=QLUqfJ1tmSEeUwBKTTiv_Qk3QGbInC2RSmlXfGXc8Wo,380
1968
+ vellum/workflows/utils/names.py,sha256=QtHquoaGqRseu5gg2OcVGI2d_CMcEOvjb9KspwH4C-A,552
1968
1969
  vellum/workflows/utils/pydantic_schema.py,sha256=eR_bBtY-T0pttJP-ARwagSdCOnwPUtiT3cegm2lzDTQ,1310
1969
1970
  vellum/workflows/utils/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1970
1971
  vellum/workflows/utils/tests/test_functions.py,sha256=TlNhD0OBJ-aeYn4qUqmApuajkx9sJx0lIQRMfT8Xf0w,23688
1971
- vellum/workflows/utils/tests/test_names.py,sha256=aOqpyvMsOEK_9mg_-yaNxQDW7QQfwqsYs37PseyLhxw,402
1972
+ vellum/workflows/utils/tests/test_names.py,sha256=DnRRnuORxQXx9ESegCzkxiWcHy2_bBi7lXgbFi3FZK8,757
1972
1973
  vellum/workflows/utils/tests/test_uuids.py,sha256=i77ABQ0M3S-aFLzDXHJq_yr5FPkJEWCMBn1HJ3DObrE,437
1973
1974
  vellum/workflows/utils/tests/test_vellum_variables.py,sha256=vbnKgm41aB5OXlO-ZIPbhQ6xDiZkT8KMxCLqz4zocWY,1791
1974
1975
  vellum/workflows/utils/uuids.py,sha256=IaZQANz7fhF7la0_J1O50Y6D2PIYv_taRDTRzBT9aWw,1284
@@ -1976,13 +1977,13 @@ vellum/workflows/utils/vellum_variables.py,sha256=YHLNiQGWDNssGH1FQoG9Z1jUFZ-zYe
1976
1977
  vellum/workflows/utils/zip.py,sha256=HVg_YZLmBOTXKaDV3Xhaf3V6sYnfqqZXQ8CpuafkbPY,1181
1977
1978
  vellum/workflows/vellum_client.py,sha256=xkfoucodxNK5JR2-lbRqZx3xzDgExWkP6kySrpi_Ubc,1079
1978
1979
  vellum/workflows/workflows/__init__.py,sha256=KY45TqvavCCvXIkyCFMEc0dc6jTMOUci93U2DUrlZYc,66
1979
- vellum/workflows/workflows/base.py,sha256=nEFaKuLQahpEAxi-3VmlIbxEcTaKJ3_1G3WNVATVvzA,28466
1980
+ vellum/workflows/workflows/base.py,sha256=4_-kEebUBCn7d4N0TxF-sQejM2gAF8N6FbGabV2t6Pw,28346
1980
1981
  vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnadGsrSZGa7t7LpJA,2008
1981
1982
  vellum/workflows/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1982
1983
  vellum/workflows/workflows/tests/test_base_workflow.py,sha256=ptMntHzVyy8ZuzNgeTuk7hREgKQ5UBdgq8VJFSGaW4Y,20832
1983
1984
  vellum/workflows/workflows/tests/test_context.py,sha256=VJBUcyWVtMa_lE5KxdhgMu0WYNYnUQUDvTF7qm89hJ0,2333
1984
- vellum_ai-1.3.5.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1985
- vellum_ai-1.3.5.dist-info/METADATA,sha256=cGN1uqwggZ4itH8f0IlQACy6h-uM2e-IspLFVz3DwKU,5547
1986
- vellum_ai-1.3.5.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1987
- vellum_ai-1.3.5.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1988
- vellum_ai-1.3.5.dist-info/RECORD,,
1985
+ vellum_ai-1.3.7.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1986
+ vellum_ai-1.3.7.dist-info/METADATA,sha256=raPRArltl5WpYibdvsHEP9v-SzQBgXazawHIkodYryY,5547
1987
+ vellum_ai-1.3.7.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1988
+ vellum_ai-1.3.7.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1989
+ vellum_ai-1.3.7.dist-info/RECORD,,
@@ -100,3 +100,20 @@ def test_serialize_display_data():
100
100
  "position": {"x": 0.0, "y": 0.0},
101
101
  "comment": {"expanded": True, "value": "I hope this works"},
102
102
  }
103
+
104
+
105
+ def test_serialize_node_label_with_pascal_case():
106
+ """
107
+ Tests that a node with PascalCase name serializes with proper title case label.
108
+ """
109
+
110
+ # GIVEN a node with a PascalCase name that includes common patterns
111
+ class MyCustomNode(BaseNode):
112
+ pass
113
+
114
+ # WHEN we serialize the node
115
+ node_display_class = get_node_display_class(MyCustomNode)
116
+ data = node_display_class().serialize(WorkflowDisplayContext())
117
+
118
+ # THEN the label should be converted to proper title case with spaces
119
+ assert data["label"] == "My Custom Node"
@@ -173,7 +173,7 @@ def test_serialize_workflow(vellum_client):
173
173
  },
174
174
  ],
175
175
  "data": {
176
- "label": "Simple A P I Node",
176
+ "label": "Simple API Node",
177
177
  "error_output_id": None,
178
178
  "source_handle_id": "7c33b4d3-9204-4bd5-9371-80ee34f83073",
179
179
  "target_handle_id": "14b538a5-aedb-41f3-b579-039956b7c7ed",
@@ -73,11 +73,15 @@ def test_serialize_workflow():
73
73
  "node_id": "8e89ae10-a709-45ec-89f8-242f92e4a83f",
74
74
  "node_output_id": "0cd09f0a-c142-4d5d-acc7-b93cd30ca58d",
75
75
  },
76
+ "constant_input": {
77
+ "type": "CONSTANT_VALUE",
78
+ "value": {"type": "STRING", "value": "constant_input"},
79
+ },
76
80
  },
77
81
  "forced": None,
78
82
  "strict": None,
79
83
  },
80
- "src": 'from vellum.workflows.utils.functions import use_tool_inputs\n\nfrom .inputs import ParentInputs\nfrom .nodes.dummy_node import DummyNode\n\n\n@use_tool_inputs(\n parent_input=ParentInputs.parent_input,\n dummy_input=DummyNode.Outputs.text,\n)\ndef get_string(parent_input: str, dummy_input: str, populated_input: str) -> str:\n """\n Get a string with the parent input, dummy input, and the populated input.\n """\n return f"This is the parent input: {parent_input}, this is the dummy input: {dummy_input}, and this is the populated input: {populated_input}" # noqa: E501\n', # noqa: E501
84
+ "src": 'from vellum.workflows.utils.functions import use_tool_inputs\n\nfrom .inputs import ParentInputs\nfrom .nodes.dummy_node import DummyNode\n\n\n@use_tool_inputs(\n parent_input=ParentInputs.parent_input,\n dummy_input=DummyNode.Outputs.text,\n constant_input="constant_input",\n)\ndef get_string(parent_input: str, dummy_input: str, constant_input: str, populated_input: str) -> str:\n """\n Get a string with the parent input, dummy input, and the populated input.\n """\n return f"parent input: {parent_input}, dummy input: {dummy_input}, constant input: {constant_input}, populated input: {populated_input}" # noqa: E501\n', # noqa: E501
81
85
  }
82
86
  ],
83
87
  },
@@ -6,8 +6,8 @@ from typing import TYPE_CHECKING, Any, Dict, List, cast
6
6
 
7
7
  from pydantic import BaseModel
8
8
 
9
- from vellum.client.types.function_definition import FunctionDefinition
10
9
  from vellum.client.types.logical_operator import LogicalOperator
10
+ from vellum.workflows.constants import undefined
11
11
  from vellum.workflows.descriptors.base import BaseDescriptor
12
12
  from vellum.workflows.expressions.accessor import AccessorExpression
13
13
  from vellum.workflows.expressions.add import AddExpression
@@ -244,7 +244,14 @@ def serialize_key(key: Any) -> str:
244
244
  return str(key)
245
245
 
246
246
 
247
+ # Sentinel value to indicate a value should be omitted from serialization
248
+ _UNDEFINED_SENTINEL: JsonObject = {"__undefined__": True}
249
+
250
+
247
251
  def serialize_value(display_context: "WorkflowDisplayContext", value: Any) -> JsonObject:
252
+ if value is undefined:
253
+ return _UNDEFINED_SENTINEL
254
+
248
255
  if isinstance(value, ConstantValueReference):
249
256
  return serialize_value(display_context, value._value)
250
257
 
@@ -315,7 +322,12 @@ def serialize_value(display_context: "WorkflowDisplayContext", value: Any) -> Js
315
322
  }
316
323
 
317
324
  if isinstance(value, list):
318
- serialized_items = [serialize_value(display_context, item) for item in value]
325
+ serialized_items = []
326
+ for item in value:
327
+ serialized_item = serialize_value(display_context, item)
328
+ if serialized_item != _UNDEFINED_SENTINEL:
329
+ serialized_items.append(serialized_item)
330
+
319
331
  if all(isinstance(item, dict) and item["type"] == "CONSTANT_VALUE" for item in serialized_items):
320
332
  constant_values = []
321
333
  for item in serialized_items:
@@ -346,14 +358,17 @@ def serialize_value(display_context: "WorkflowDisplayContext", value: Any) -> Js
346
358
  return serialize_value(display_context, dict_value)
347
359
 
348
360
  if isinstance(value, dict):
349
- serialized_entries: List[Dict[str, Any]] = [
350
- {
351
- "id": str(uuid4_from_hash(f"{key}|{val}")),
352
- "key": serialize_key(key),
353
- "value": serialize_value(display_context, val),
354
- }
355
- for key, val in value.items()
356
- ]
361
+ serialized_entries: List[Dict[str, Any]] = []
362
+ for key, val in value.items():
363
+ serialized_val = serialize_value(display_context, val)
364
+ if serialized_val != _UNDEFINED_SENTINEL:
365
+ serialized_entries.append(
366
+ {
367
+ "id": str(uuid4_from_hash(f"{key}|{val}")),
368
+ "key": serialize_key(key),
369
+ "value": serialized_val,
370
+ }
371
+ )
357
372
 
358
373
  # Check if all entries have constant values
359
374
  if all(entry["value"]["type"] == "CONSTANT_VALUE" for entry in serialized_entries):
@@ -423,6 +438,10 @@ def serialize_value(display_context: "WorkflowDisplayContext", value: Any) -> Js
423
438
 
424
439
  if callable(value):
425
440
  function_definition = compile_function_definition(value)
441
+
442
+ name = function_definition.name
443
+ description = function_definition.description or ""
444
+
426
445
  inputs = getattr(value, "__vellum_inputs__", {})
427
446
 
428
447
  if inputs:
@@ -432,7 +451,9 @@ def serialize_value(display_context: "WorkflowDisplayContext", value: Any) -> Js
432
451
 
433
452
  model_data = function_definition.model_dump()
434
453
  model_data["inputs"] = serialized_inputs
435
- function_definition = FunctionDefinition.model_validate(model_data)
454
+ function_definition_data = model_data
455
+ else:
456
+ function_definition_data = function_definition.model_dump()
436
457
 
437
458
  source_path = inspect.getsourcefile(value)
438
459
  if source_path is not None:
@@ -447,9 +468,9 @@ def serialize_value(display_context: "WorkflowDisplayContext", value: Any) -> Js
447
468
  "type": "JSON",
448
469
  "value": {
449
470
  "type": "CODE_EXECUTION",
450
- "name": function_definition.name,
451
- "description": function_definition.description,
452
- "definition": function_definition.model_dump(),
471
+ "name": name,
472
+ "description": description,
473
+ "definition": function_definition_data,
453
474
  "src": source_code,
454
475
  },
455
476
  },
@@ -599,7 +599,7 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
599
599
 
600
600
  workflow_output_display = self.output_displays.get(workflow_output)
601
601
  workflow_output_displays[workflow_output] = (
602
- workflow_output_display or self._generate_workflow_output_display(workflow_output, self._workflow)
602
+ workflow_output_display or self._generate_workflow_output_display(workflow_output)
603
603
  )
604
604
 
605
605
  return WorkflowDisplayContext(
@@ -688,14 +688,8 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
688
688
 
689
689
  return EntrypointDisplay(id=entrypoint_id, edge_display=edge_display)
690
690
 
691
- def _generate_workflow_output_display(
692
- self, output: OutputReference, workflow_class: Type[BaseWorkflow]
693
- ) -> WorkflowOutputDisplay:
694
- # TODO: use the output.id field instead once we add `__parent_class__` to BaseWorkflow.Outputs
695
- output_id = workflow_class.__output_ids__.get(output.name) or uuid4_from_hash(
696
- f"{self.workflow_id}|id|{output.name}"
697
- )
698
- return WorkflowOutputDisplay(id=output_id, name=output.name)
691
+ def _generate_workflow_output_display(self, output: OutputReference) -> WorkflowOutputDisplay:
692
+ return WorkflowOutputDisplay(id=output.id, name=output.name)
699
693
 
700
694
  def __init_subclass__(cls, **kwargs: Any) -> None:
701
695
  super().__init_subclass__(**kwargs)