vellum-ai 0.14.77__py3-none-any.whl → 0.14.79__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 (29) hide show
  1. vellum/client/core/client_wrapper.py +1 -1
  2. vellum/client/types/code_execution_package.py +2 -1
  3. vellum/plugins/pydantic.py +4 -1
  4. vellum/plugins/tests/__init__.py +0 -0
  5. vellum/plugins/tests/test_pydantic.py +30 -0
  6. vellum/prompts/__init__.py +3 -0
  7. vellum/prompts/blocks/__init__.py +3 -0
  8. vellum/prompts/blocks/helpers.py +31 -0
  9. vellum/workflows/expressions/accessor.py +31 -2
  10. vellum/workflows/expressions/tests/test_accessor.py +59 -0
  11. vellum/workflows/nodes/experimental/tool_calling_node/utils.py +6 -1
  12. vellum/workflows/state/encoder.py +10 -3
  13. vellum/workflows/types/utils.py +5 -2
  14. vellum/workflows/utils/vellum_variables.py +37 -0
  15. {vellum_ai-0.14.77.dist-info → vellum_ai-0.14.79.dist-info}/METADATA +1 -1
  16. {vellum_ai-0.14.77.dist-info → vellum_ai-0.14.79.dist-info}/RECORD +29 -26
  17. vellum_cli/__init__.py +2 -2
  18. vellum_cli/push.py +21 -6
  19. vellum_cli/tests/test_push.py +60 -0
  20. vellum_ee/workflows/display/nodes/vellum/base_adornment_node.py +3 -3
  21. vellum_ee/workflows/display/nodes/vellum/tests/test_tool_calling_node.py +8 -5
  22. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +48 -15
  23. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_prompt_node_serialization.py +52 -0
  24. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_serialization.py +2 -2
  25. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_workflow_deployment_serialization.py +48 -3
  26. vellum_ee/workflows/display/utils/expressions.py +8 -2
  27. {vellum_ai-0.14.77.dist-info → vellum_ai-0.14.79.dist-info}/LICENSE +0 -0
  28. {vellum_ai-0.14.77.dist-info → vellum_ai-0.14.79.dist-info}/WHEEL +0 -0
  29. {vellum_ai-0.14.77.dist-info → vellum_ai-0.14.79.dist-info}/entry_points.txt +0 -0
@@ -18,7 +18,7 @@ class BaseClientWrapper:
18
18
  headers: typing.Dict[str, str] = {
19
19
  "X-Fern-Language": "Python",
20
20
  "X-Fern-SDK-Name": "vellum-ai",
21
- "X-Fern-SDK-Version": "0.14.77",
21
+ "X-Fern-SDK-Version": "0.14.79",
22
22
  }
23
23
  headers["X-API-KEY"] = self.api_key
24
24
  return headers
@@ -1,14 +1,15 @@
1
1
  # This file was auto-generated by Fern from our API Definition.
2
2
 
3
3
  from ..core.pydantic_utilities import UniversalBaseModel
4
- from ..core.pydantic_utilities import IS_PYDANTIC_V2
5
4
  import typing
5
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2
6
6
  import pydantic
7
7
 
8
8
 
9
9
  class CodeExecutionPackage(UniversalBaseModel):
10
10
  version: str
11
11
  name: str
12
+ repository: typing.Optional[str] = None
12
13
 
13
14
  if IS_PYDANTIC_V2:
14
15
  model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
@@ -71,7 +71,10 @@ class OnValidatePython(ValidatePythonHandlerProtocol):
71
71
  self.tracked_descriptors[key] = value
72
72
  # TODO: This does not yet work for descriptors that map to more complex types
73
73
  # https://app.shortcut.com/vellum/story/4636
74
- input[key] = value.types[0]()
74
+ if len(value.types) == 0:
75
+ input[key] = dict()
76
+ else:
77
+ input[key] = value.types[0]()
75
78
 
76
79
  def on_success(self, result: Any) -> None:
77
80
  if self.tracked_descriptors:
File without changes
@@ -0,0 +1,30 @@
1
+ from typing import Any
2
+
3
+ from pydantic import BaseModel
4
+
5
+ from vellum.workflows.expressions.accessor import AccessorExpression
6
+ from vellum.workflows.references.constant import ConstantValueReference
7
+ from vellum.workflows.state.base import BaseState
8
+
9
+
10
+ class TestState(BaseState):
11
+ pass
12
+
13
+
14
+ class TestModel(BaseModel):
15
+ field: Any
16
+
17
+
18
+ def test_pydantic_plugin__empty_types_descriptor():
19
+ """
20
+ Test that the pydantic plugin handles BaseDescriptor with empty types gracefully.
21
+ """
22
+
23
+ base_ref = ConstantValueReference({"name": "test"})
24
+ accessor = AccessorExpression(base=base_ref, field="name")
25
+
26
+ model = TestModel(field=accessor)
27
+
28
+ assert model is not None
29
+ assert hasattr(model, "field")
30
+ assert model.field == accessor
@@ -0,0 +1,3 @@
1
+ from .blocks import TextSystemMessage, TextUserMessage
2
+
3
+ __all__ = ["TextSystemMessage", "TextUserMessage"]
@@ -0,0 +1,3 @@
1
+ from .helpers import TextSystemMessage, TextUserMessage
2
+
3
+ __all__ = ["TextSystemMessage", "TextUserMessage"]
@@ -0,0 +1,31 @@
1
+ from vellum import ChatMessagePromptBlock, PlainTextPromptBlock, RichTextPromptBlock
2
+
3
+
4
+ def TextSystemMessage(content: str) -> ChatMessagePromptBlock:
5
+ """
6
+ Create a text system message that autocasts to ChatMessagePromptBlock.
7
+
8
+ Args:
9
+ content: The text content for the system message
10
+
11
+ Returns:
12
+ ChatMessagePromptBlock configured as a system message
13
+ """
14
+ return ChatMessagePromptBlock(
15
+ chat_role="SYSTEM", blocks=[RichTextPromptBlock(blocks=[PlainTextPromptBlock(text=content)])]
16
+ )
17
+
18
+
19
+ def TextUserMessage(content: str) -> ChatMessagePromptBlock:
20
+ """
21
+ Create a text user message that autocasts to ChatMessagePromptBlock.
22
+
23
+ Args:
24
+ content: The text content for the user message
25
+
26
+ Returns:
27
+ ChatMessagePromptBlock configured as a user message
28
+ """
29
+ return ChatMessagePromptBlock(
30
+ chat_role="USER", blocks=[RichTextPromptBlock(blocks=[PlainTextPromptBlock(text=content)])]
31
+ )
@@ -1,6 +1,6 @@
1
1
  from collections.abc import Mapping
2
2
  import dataclasses
3
- from typing import Any, Sequence, Type, TypeVar, Union
3
+ from typing import Any, Sequence, Type, TypeVar, Union, get_args, get_origin
4
4
 
5
5
  from pydantic import BaseModel, GetCoreSchemaHandler
6
6
  from pydantic_core import core_schema
@@ -22,12 +22,41 @@ class AccessorExpression(BaseDescriptor[Any]):
22
22
  ) -> None:
23
23
  super().__init__(
24
24
  name=f"{base.name}.{field}",
25
- types=(),
25
+ types=self._infer_accessor_types(base, field),
26
26
  instance=None,
27
27
  )
28
28
  self._base = base
29
29
  self._field = field
30
30
 
31
+ def _infer_accessor_types(self, base: BaseDescriptor[LHS], field: Union[str, int]) -> tuple[Type, ...]:
32
+ """
33
+ Infer the types for this accessor expression based on the base descriptor's types
34
+ and the field being accessed.
35
+ """
36
+ if not base.types:
37
+ return ()
38
+
39
+ inferred_types = []
40
+
41
+ for base_type in base.types:
42
+ origin = get_origin(base_type)
43
+ args = get_args(base_type)
44
+
45
+ if isinstance(field, int) and origin in (list, tuple) and args:
46
+ if origin is list:
47
+ inferred_types.append(args[0])
48
+ elif origin is tuple and len(args) == 2 and args[1] is ...:
49
+ inferred_types.append(args[0])
50
+ elif origin is tuple and len(args) > abs(field):
51
+ if field >= 0:
52
+ inferred_types.append(args[field])
53
+ else:
54
+ inferred_types.append(args[field])
55
+ elif isinstance(field, str) and origin in (dict,) and len(args) >= 2:
56
+ inferred_types.append(args[1]) # Value type from Dict[K, V]
57
+
58
+ return tuple(set(inferred_types)) if inferred_types else ()
59
+
31
60
  def resolve(self, state: "BaseState") -> Any:
32
61
  base = resolve_value(self._base, state)
33
62
 
@@ -1,11 +1,14 @@
1
1
  import pytest
2
2
  from dataclasses import dataclass
3
+ from typing import Dict, List
3
4
 
4
5
  from pydantic import BaseModel
5
6
 
6
7
  from vellum.workflows.descriptors.exceptions import InvalidExpressionException
7
8
  from vellum.workflows.expressions.accessor import AccessorExpression
9
+ from vellum.workflows.outputs.base import BaseOutputs
8
10
  from vellum.workflows.references.constant import ConstantValueReference
11
+ from vellum.workflows.references.output import OutputReference
9
12
  from vellum.workflows.state.base import BaseState
10
13
 
11
14
 
@@ -187,3 +190,59 @@ def test_accessor_expression_unsupported_type():
187
190
  accessor.resolve(state)
188
191
 
189
192
  assert "Cannot get field field from 42" in str(exc_info.value)
193
+
194
+
195
+ def test_accessor_expression_list_type_inference():
196
+ """Test that accessor expressions correctly infer element types from List[str]."""
197
+ base_ref: OutputReference = OutputReference(
198
+ name="test_list",
199
+ types=(List[str],),
200
+ instance=None,
201
+ outputs_class=BaseOutputs,
202
+ )
203
+
204
+ accessor = AccessorExpression(base=base_ref, field=0)
205
+
206
+ assert accessor.types == (str,)
207
+
208
+
209
+ def test_accessor_expression_tuple_type_inference():
210
+ """Test that accessor expressions correctly infer element types from Tuple types."""
211
+ base_ref: OutputReference = OutputReference(
212
+ name="test_tuple",
213
+ types=(tuple,),
214
+ instance=None,
215
+ outputs_class=BaseOutputs,
216
+ )
217
+
218
+ accessor = AccessorExpression(base=base_ref, field=0)
219
+
220
+ assert accessor.types == ()
221
+
222
+
223
+ def test_accessor_expression_dict_type_inference():
224
+ """Test that accessor expressions correctly infer value types from Dict types."""
225
+ base_ref: OutputReference = OutputReference(
226
+ name="test_dict",
227
+ types=(Dict[str, int],),
228
+ instance=None,
229
+ outputs_class=BaseOutputs,
230
+ )
231
+
232
+ accessor = AccessorExpression(base=base_ref, field="some_key")
233
+
234
+ assert accessor.types == (int,)
235
+
236
+
237
+ def test_accessor_expression_empty_base_types():
238
+ """Test that accessor expressions handle empty base types gracefully."""
239
+ base_ref: OutputReference = OutputReference(
240
+ name="test_empty",
241
+ types=(),
242
+ instance=None,
243
+ outputs_class=BaseOutputs,
244
+ )
245
+
246
+ accessor = AccessorExpression(base=base_ref, field=0)
247
+
248
+ assert accessor.types == ()
@@ -251,7 +251,12 @@ def create_function_node(
251
251
  )
252
252
  else:
253
253
  # For regular functions, use CodeExecutionNode approach
254
- function_source = inspect.getsource(function)
254
+ # function tool must be put in another file (no need to have the same name)
255
+ source_path = inspect.getmodule(function)
256
+ if source_path is not None:
257
+ function_source = inspect.getsource(source_path)
258
+ else:
259
+ function_source = f"<source code not available for {function.__name__}>"
255
260
  function_name = function.__name__
256
261
 
257
262
  code = f'''
@@ -10,6 +10,7 @@ from typing import Any, Callable, Dict, Type
10
10
  from pydantic import BaseModel
11
11
 
12
12
  from vellum.workflows.constants import undefined
13
+ from vellum.workflows.expressions.coalesce_expression import CoalesceExpression
13
14
  from vellum.workflows.inputs.base import BaseInputs
14
15
  from vellum.workflows.outputs.base import BaseOutput, BaseOutputs
15
16
  from vellum.workflows.ports.port import Port
@@ -21,6 +22,10 @@ class DefaultStateEncoder(JSONEncoder):
21
22
  encoders: Dict[Type, Callable] = {}
22
23
 
23
24
  def default(self, obj: Any) -> Any:
25
+ if isinstance(obj, CoalesceExpression):
26
+ empty_state = BaseState()
27
+ return self.default(obj.resolve(empty_state))
28
+
24
29
  if isinstance(obj, BaseState):
25
30
  return dict(obj)
26
31
 
@@ -61,9 +66,11 @@ class DefaultStateEncoder(JSONEncoder):
61
66
 
62
67
  if callable(obj):
63
68
  function_definition = compile_function_definition(obj)
64
- try:
65
- source_code = inspect.getsource(obj)
66
- except Exception:
69
+ source_path = inspect.getsourcefile(obj)
70
+ if source_path is not None:
71
+ with open(source_path, "r") as f:
72
+ source_code = f.read()
73
+ else:
67
74
  source_code = f"<source code not available for {obj.__name__}>"
68
75
 
69
76
  return {
@@ -49,9 +49,12 @@ def resolve_combined_types(
49
49
  lhs_types = resolve_types(lhs)
50
50
  rhs_types = resolve_types(rhs)
51
51
 
52
- unique_results = set(lhs_types) | set(rhs_types)
52
+ result_types: List[Union[Type[_LHS], Type[_RHS]]] = list(lhs_types)
53
+ for rhs_type in rhs_types:
54
+ if rhs_type not in result_types:
55
+ result_types.append(rhs_type)
53
56
 
54
- return tuple(unique_results)
57
+ return tuple(result_types)
55
58
 
56
59
 
57
60
  def infer_types(object_: Type, attr_name: str, localns: Optional[Dict[str, Any]] = None) -> Tuple[Type, ...]:
@@ -50,6 +50,11 @@ def primitive_type_to_vellum_variable_type(type_: Union[Type, BaseDescriptor]) -
50
50
  # Number now supports float and int
51
51
  elif types == [float, int]:
52
52
  return "NUMBER"
53
+
54
+ collapse_types = _collapse_types(types)
55
+ if len(collapse_types) == 1:
56
+ return primitive_type_to_vellum_variable_type(collapse_types[0])
57
+
53
58
  raise ValueError(f"Expected Descriptor to only have one type, got {types}")
54
59
 
55
60
  type_ = type_.types[0]
@@ -129,3 +134,35 @@ def _is_type_optionally_equal(type_: Type, target_type: Type) -> bool:
129
134
 
130
135
  def _is_type_optionally_in(type_: Type, target_types: Tuple[Type, ...]) -> bool:
131
136
  return any(_is_type_optionally_equal(type_, target_type) for target_type in target_types)
137
+
138
+
139
+ def _collapse_types(types: List[Type]) -> List[Type]:
140
+ """
141
+ Collapses a list of types into a list of types that are not subtypes of each other.
142
+ What remains are the "most specific" types.
143
+ """
144
+
145
+ new_types: List[Type] = []
146
+ for target_type in types:
147
+ if any(_is_subtype(source_type, target_type) for source_type in new_types):
148
+ continue
149
+
150
+ new_types.append(target_type)
151
+
152
+ return new_types
153
+
154
+
155
+ def _is_subtype(source_type: Type, target_type: Type) -> bool:
156
+ """
157
+ Checks if `source_type` is a strict subtype of `target_type`. Meaning all values that are
158
+ of type `source_type` are also of type `target_type`.
159
+ """
160
+
161
+ if source_type == target_type:
162
+ return True
163
+
164
+ source_origin = get_origin(source_type)
165
+ if source_origin == target_type:
166
+ return True
167
+
168
+ return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vellum-ai
3
- Version: 0.14.77
3
+ Version: 0.14.79
4
4
  Summary:
5
5
  License: MIT
6
6
  Requires-Python: >=3.9,<4.0
@@ -1,6 +1,6 @@
1
1
  vellum_cli/CONTRIBUTING.md,sha256=FtDC7BGxSeMnwCXAUssFsAIElXtmJE-O5Z7BpolcgvI,2935
2
2
  vellum_cli/README.md,sha256=2NudRoLzWxNKqnuVy1JuQ7DerIaxWGYkrH8kMd-asIE,90
3
- vellum_cli/__init__.py,sha256=oi-vvNVepu23IBBjhA5uUIDVYBPqQ3EzxWZAPn2S64c,12700
3
+ vellum_cli/__init__.py,sha256=50dYVkBzGUS1i-UKf_9zv1JMif1lLClriNUSs-Z7i4E,12678
4
4
  vellum_cli/aliased_group.py,sha256=ugW498j0yv4ALJ8vS9MsO7ctDW7Jlir9j6nE_uHAP8c,3363
5
5
  vellum_cli/config.py,sha256=v5BmZ-t_v4Jmqd7KVuQMZF2pRI-rbMspSkVYXIRoTmI,9448
6
6
  vellum_cli/image_push.py,sha256=rPeSfTlFpdTzwTdnXRL82OVd61qMoGFGLxnLjZLU98Q,10596
@@ -8,7 +8,7 @@ vellum_cli/init.py,sha256=WpnMXPItPmh0f0bBGIer3p-e5gu8DUGwSArT_FuoMEw,5093
8
8
  vellum_cli/logger.py,sha256=dcM_OmgqXLo93vDYswO5ylyUQQcTfnA5GTd5tbIt3wM,1446
9
9
  vellum_cli/ping.py,sha256=p_BCCRjgPhng6JktuECtkDQLbhopt6JpmrtGoLnLJT8,1161
10
10
  vellum_cli/pull.py,sha256=udYyPlJ6VKDdh78rApNJOZgxHl82fcV6iGnRPSdX1LY,14750
11
- vellum_cli/push.py,sha256=ibAaf6zO41Qrgfholl18bCq8sWVYd2PDCiQsPkEYAFw,10296
11
+ vellum_cli/push.py,sha256=sUo0d7lm7saGxQciH-JW2FB_gWfP2gwoEHO1wGnNQR0,10933
12
12
  vellum_cli/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  vellum_cli/tests/conftest.py,sha256=wx3PlJjVB0HRf5dr2b_idOIw27WPPl0J0FNbhIJJaVk,1689
14
14
  vellum_cli/tests/test_config.py,sha256=uvKGDc8BoVyT9_H0Z-g8469zVxomn6Oi3Zj-vK7O_wU,2631
@@ -18,7 +18,7 @@ vellum_cli/tests/test_init.py,sha256=8UOc_ThfouR4ja5cCl_URuLk7ohr9JXfCnG4yka1OUQ
18
18
  vellum_cli/tests/test_main.py,sha256=qDZG-aQauPwBwM6A2DIu1494n47v3pL28XakTbLGZ-k,272
19
19
  vellum_cli/tests/test_ping.py,sha256=178EJHxPZtnnPMNXXynsQt8DIFhsrdc2bL17_YsG17M,2580
20
20
  vellum_cli/tests/test_pull.py,sha256=hxMbW_j0weDDrkzVGpvLpFcwNQdn-fxTv4wBHeYizzc,49904
21
- vellum_cli/tests/test_push.py,sha256=rasQsxMYsSKgi_iaYz5cBD2ZBHusxhG9FAPx1Tn7mE4,35382
21
+ vellum_cli/tests/test_push.py,sha256=wk9jQTV565TeukR0Vz-2AUQyJa3VlOJrmWxkSTX_Ptw,37860
22
22
  vellum_ee/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
23
  vellum_ee/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  vellum_ee/workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -35,7 +35,7 @@ vellum_ee/workflows/display/nodes/types.py,sha256=St1BB6no528OyELGiyRabWao0GGw6m
35
35
  vellum_ee/workflows/display/nodes/utils.py,sha256=sloya5TpXsnot1HURc9L51INwflRqUzHxRVnCS9Cd-4,973
36
36
  vellum_ee/workflows/display/nodes/vellum/__init__.py,sha256=nUIgH2s0-7IbQRNrBhLPyRNe8YIrx3Yo9HeeW-aXXFk,1668
37
37
  vellum_ee/workflows/display/nodes/vellum/api_node.py,sha256=5Uq8x08F64yrBcqbfsVeuoGnTa9eoOPumYzZZrDPmr0,8847
38
- vellum_ee/workflows/display/nodes/vellum/base_adornment_node.py,sha256=rJbHZBg9A_v2bjk-R6MfWzShcrS2gcKIOyYGoqwTx8s,6353
38
+ vellum_ee/workflows/display/nodes/vellum/base_adornment_node.py,sha256=FHhPoGmmny4Xcxi2pm12Sk3ZOREanWEVrOWcjRhncH4,6337
39
39
  vellum_ee/workflows/display/nodes/vellum/code_execution_node.py,sha256=6lavdBw297GwAQqyxjnPUtx5pHv6k5V9Vkuq7s2D0TM,4508
40
40
  vellum_ee/workflows/display/nodes/vellum/conditional_node.py,sha256=9GtbvSJUNF626tCYxnMxETVZm3Fq84vOZ3Nkdkl3n-M,11146
41
41
  vellum_ee/workflows/display/nodes/vellum/error_node.py,sha256=YhMsi2TG1zSR8E7IpxzzSncOyVLcvqTuGa3mr4RqHd8,2364
@@ -62,7 +62,7 @@ vellum_ee/workflows/display/nodes/vellum/tests/test_retry_node.py,sha256=h93ysol
62
62
  vellum_ee/workflows/display/nodes/vellum/tests/test_search_node.py,sha256=KvByxgbUkVyfPIVxTUBUk6a92JiJMi8eReZWxzfPExU,3864
63
63
  vellum_ee/workflows/display/nodes/vellum/tests/test_subworkflow_deployment_node.py,sha256=BUzHJgjdWnPeZxjFjHfDBKnbFjYjnbXPjc-1hne1B2Y,3965
64
64
  vellum_ee/workflows/display/nodes/vellum/tests/test_templating_node.py,sha256=LSk2gx9TpGXbAqKe8dggQW8yJZqj-Cf0EGJFeGGlEcw,3321
65
- vellum_ee/workflows/display/nodes/vellum/tests/test_tool_calling_node.py,sha256=ZsLIGnJ9QKrXjYeDW8LEN8M9FnWRQ9TohHFyB6144HY,7970
65
+ vellum_ee/workflows/display/nodes/vellum/tests/test_tool_calling_node.py,sha256=YMoLNWknmSsFj7MtprenOYuXTX1VWUQ2bXZs_p76gBg,8163
66
66
  vellum_ee/workflows/display/nodes/vellum/tests/test_try_node.py,sha256=Khjsb53PKpZuyhKoRMgKAL45eGp5hZqXvHmVeQWRw4w,2289
67
67
  vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py,sha256=3LS1O4DGPWit05oj_ubeW8AlHGnoBxdUMferGQuAiZs,4851
68
68
  vellum_ee/workflows/display/nodes/vellum/try_node.py,sha256=z9Omo676RRc7mQjLoL7hjiHhUj0OWVLhrrb97YTN4QA,4086
@@ -72,7 +72,7 @@ vellum_ee/workflows/display/tests/test_base_workflow_display.py,sha256=axUOLwpIh
72
72
  vellum_ee/workflows/display/tests/workflow_serialization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
73
73
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
74
74
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py,sha256=XOQDDRiG46etxTC7-_RUEutoNumXc02fo7oho4GYM0c,1900
75
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py,sha256=IuoR3QrsnshZSb1ggLBvQJnTw244lHBo70KmKLd0fwk,12852
75
+ vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py,sha256=aEmF6zpmmHdFgiG4V81EweOk5qO6cfukR782dYSE960,14060
76
76
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py,sha256=DFNp_iUxlyE-zCJBH9ab3e1jQEK-NSE9M2CQd4NCjY8,24853
77
77
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py,sha256=s6_mnk0pkztU59wYpSfOFpMhAJaRjmyfxM6WJGtnD4Y,6456
78
78
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py,sha256=PkSgghJDz0fpDB72HHPjLjo8LkZk-HpUkCQzRLX-iVw,40611
@@ -84,7 +84,7 @@ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_default_stat
84
84
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py,sha256=w1BYEZXIMjWmcKGQXzhelHnKFlEAXmsgjkI9fcgqKXA,5850
85
85
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py,sha256=-T0cd2jx1bC0ZNtAESF78fnYD_0nOqo8zMMLwRHUTRM,6227
86
86
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py,sha256=PZ9Yec8D6e9wM2kh5eWtNvK5BghTf1RdvoSW5_pw3FM,7384
87
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_prompt_node_serialization.py,sha256=tljn-ueIMEW3j2q6Ni9O852sdQMjut05ox4paBeJjm8,23714
87
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_prompt_node_serialization.py,sha256=vVqxXHieRUPP1Rt4ITnjMxuGU52WBfifoEzPyHQnd7w,25618
88
88
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py,sha256=3Djct7lIr2TPW-wDd_t6eoNdsE0hBOj9OwKWRroXMUo,21659
89
89
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py,sha256=91u9FWLErrNGfUkZ22ifk6IazGtaYoDFbZYjhxEESgI,16579
90
90
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py,sha256=rtkAQw5awOFX3pWh0qz3f766-tTnPhToGsXVSHO4M4U,8352
@@ -94,8 +94,8 @@ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_
94
94
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py,sha256=V8b6gKghLlO7PJI8xeNdnfn8aII0W_IFQvSQBQM62UQ,7721
95
95
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py,sha256=hDWtKXmGI1CKhTwTNqpu_d5RkE5n7SolMLtgd87KqTI,3856
96
96
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_serialization.py,sha256=6q-lTGMp5HbQba3NsHUFSit8_zEBxIVPGE8yCw4SVx0,25720
97
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_serialization.py,sha256=36-fpwj53JcRmo7RuHrsS6ZjJ3q4j8BC1wuKruBjIt8,9137
98
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_workflow_deployment_serialization.py,sha256=zlb0Kfg1zqJsz1tD_1O-hkSKhV4-gfYI6AkK4-Yjk7U,2315
97
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_serialization.py,sha256=aY76l9s_2nezx7hCfUZsPYFzvYMy-Rjd73G0DlL6s6A,9348
98
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_workflow_deployment_serialization.py,sha256=mova0sPD3evHiHIN1O0VynxlCp-uOcEIKve5Pd_oCDg,4069
99
99
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py,sha256=pLCyMScV88DTBXRH7jXaXOEA1GBq8NIipCUFwIAWnwI,2771
100
100
  vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py,sha256=J4ouI8KxbMfxQP2Zq_9cWMGYgbjCWmKzjCJEtnSJb0I,5829
101
101
  vellum_ee/workflows/display/tests/workflow_serialization/test_workflow_input_parameterization_error.py,sha256=vAdmn3YTBDpo55znbydQxsgg9ASqHcvsUPwiBR_7wfo,1461
@@ -103,7 +103,7 @@ vellum_ee/workflows/display/types.py,sha256=i4T7ElU5b5h-nA1i3scmEhO1BqmNDc4eJDHa
103
103
  vellum_ee/workflows/display/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
104
104
  vellum_ee/workflows/display/utils/auto_layout.py,sha256=f4GiLn_LazweupfqTpubcdtdfE_vrOcmZudSsnYIY9E,3906
105
105
  vellum_ee/workflows/display/utils/exceptions.py,sha256=LSwwxCYNxFkf5XMUcFkaZKpQ13OSrI7y_bpEUwbKVk0,169
106
- vellum_ee/workflows/display/utils/expressions.py,sha256=KxEl8yNx0yPvy0y84qABef5DwxRYGm0jgDd89i6PhSE,15534
106
+ vellum_ee/workflows/display/utils/expressions.py,sha256=H5_yWpX4QQNr83iIIocOHddTpktsHbVDp1ylayvjjTE,15840
107
107
  vellum_ee/workflows/display/utils/registry.py,sha256=fWIm5Jj-10gNFjgn34iBu4RWv3Vd15ijtSN0V97bpW8,1513
108
108
  vellum_ee/workflows/display/utils/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
109
109
  vellum_ee/workflows/display/utils/tests/test_auto_layout.py,sha256=vfXI769418s9vda5Gb5NFBH747WMOwSgHRXeLCTLVm8,2356
@@ -144,7 +144,7 @@ vellum/client/README.md,sha256=CuGUYnaE0Imt0KqQ4sIPaUghCjLHkF3DdEvZWu14-8s,4807
144
144
  vellum/client/__init__.py,sha256=AYopGv2ZRVn3zsU8_km6KOvEHDbXiTPCVuYVI7bWvdA,120166
145
145
  vellum/client/core/__init__.py,sha256=SQ85PF84B9MuKnBwHNHWemSGuy-g_515gFYNFhvEE0I,1438
146
146
  vellum/client/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
147
- vellum/client/core/client_wrapper.py,sha256=3d_rKaMktUFHpsEuOeVzjJA8WivXt89sMCtRJpKKYRc,1869
147
+ vellum/client/core/client_wrapper.py,sha256=Q1F5IAmbUhtpL6ilvnpt5ixi8uWvRrlgvSV3JXJyybU,1869
148
148
  vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
149
149
  vellum/client/core/file.py,sha256=d4NNbX8XvXP32z8KpK2Xovv33nFfruIrpz0QWxlgpZk,2663
150
150
  vellum/client/core/http_client.py,sha256=Z77OIxIbL4OAB2IDqjRq_sYa5yNYAWfmdhdCSSvh6Y4,19552
@@ -265,7 +265,7 @@ vellum/client/types/code_execution_node_result_data.py,sha256=yLRzycagwxgwi-NGx8
265
265
  vellum/client/types/code_execution_node_result_output.py,sha256=ZddnayoP01i5alC12OaoNdSgLoXr_Y4Nl343xGJvJeU,1069
266
266
  vellum/client/types/code_execution_node_search_results_result.py,sha256=yPh94v7pgFL-4x1JPSnXXGihUi42i-OfOaNVHLN4jE8,740
267
267
  vellum/client/types/code_execution_node_string_result.py,sha256=uH6KO57muMko4u_xISchhvP0E-VzJfhKD_rijXgisZ8,655
268
- vellum/client/types/code_execution_package.py,sha256=2cPKwG_5pxbHND-ChLH-4lk4O5TRWSv3KCsxNZYXZyw,580
268
+ vellum/client/types/code_execution_package.py,sha256=ONMwxtIcz6zSZOd0wKaPC4Rz6S_scbYeiNZHuDMD8U4,624
269
269
  vellum/client/types/code_execution_runtime.py,sha256=ucMXj7mUYl9-B_KentTfRuRIeDq33PV3OV_GWKiG-lo,181
270
270
  vellum/client/types/code_executor_input.py,sha256=Dj6XRaIRHjbXDZ-wR_XusJkrxYD_lJ1-UZY0Ga4xeqI,694
271
271
  vellum/client/types/code_executor_response.py,sha256=Xj2d86RMtodxHdfa4L0iaMkwyF0FgM7y6uBK-8WwOgE,673
@@ -834,13 +834,16 @@ vellum/evaluations/utils/env.py,sha256=Xj_nxsoU5ox06EOTjRopR4lrigQI6Le6qbWGltYoE
834
834
  vellum/evaluations/utils/exceptions.py,sha256=dXMAkzqbHV_AP5FjjbegPlfUE0zQDlpA3qOsoOJUxfg,49
835
835
  vellum/evaluations/utils/paginator.py,sha256=rEED_BJAXAM6tM1yMwHePNzszjq_tTq4NbQvi1jWQ_Q,697
836
836
  vellum/plugins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
837
- vellum/plugins/pydantic.py,sha256=j4ApZ5WyaoCX6v54qNoShhMFyft_uKWTkyAFz5wbcgg,3619
837
+ vellum/plugins/pydantic.py,sha256=GmNsxupKskbqpe4N5NBmSnLo680EATqhXJHABgf1NO0,3727
838
+ vellum/plugins/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
839
+ vellum/plugins/tests/test_pydantic.py,sha256=S6bLqs3Y5DGA012QV_7f6hk4e6Bz-iJ9py9DEKuo4fM,746
838
840
  vellum/plugins/utils.py,sha256=cPmxE9R2CK1bki2jKE8rB-G9zMf2pzHjSPDHFPXwd3Q,878
839
841
  vellum/plugins/vellum_mypy.py,sha256=hfjC2rIxNdQuJa6fIN4PDgODnQ3YaUszyaV2eNbLJlE,27952
840
- vellum/prompts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
841
- vellum/prompts/blocks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
842
+ vellum/prompts/__init__.py,sha256=kn-btvQOMNnnBuyQiUpie48_VBJAk7tFFU-ul5dwK60,107
843
+ vellum/prompts/blocks/__init__.py,sha256=Zwvncjd8sUCPmT-8pFpgLYsKJl0xB6td1GTQzjV9hYA,108
842
844
  vellum/prompts/blocks/compilation.py,sha256=qeC_4La5auQkm4EyzCMpN34F5R8mjiGcLV7IxKgVf3k,9973
843
845
  vellum/prompts/blocks/exceptions.py,sha256=vmk5PV6Vyw9nKjZYQDUDW0LH8MfQNIgFvFb_mFWdIRI,50
846
+ vellum/prompts/blocks/helpers.py,sha256=7G1Qi6N3V1K73iqTypMTcl6Rum7wk449yHStkakLy-U,961
844
847
  vellum/prompts/blocks/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
845
848
  vellum/prompts/blocks/tests/test_compilation.py,sha256=EOUtdzJDFGbGhoc_y5XTMyO0HOpOM7FYJssPzd_yRVg,5235
846
849
  vellum/prompts/blocks/types.py,sha256=6aSJQco-5kKeadfKVVXF_SrQPlIJgMYVNc-C7so1sY8,975
@@ -1528,7 +1531,7 @@ vellum/workflows/events/types.py,sha256=LwgFlMRbptJvdPtPO1POUtGtbhGw7BSuvgHxNSgS
1528
1531
  vellum/workflows/events/workflow.py,sha256=7rb1evKsTCRUdCnisAM5Anc19ZKGxnsmzwOOv6jwWEI,7761
1529
1532
  vellum/workflows/exceptions.py,sha256=NiBiR3ggfmPxBVqD-H1SqmjI-7mIn0EStSN1BqApvCM,1213
1530
1533
  vellum/workflows/expressions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1531
- vellum/workflows/expressions/accessor.py,sha256=1kY0sYfednQ_u0kh1Df2WTsDREVIOzU7UuZc5jvj5xw,2861
1534
+ vellum/workflows/expressions/accessor.py,sha256=4OvF9JQKHSyYLTz7gGprcw3Da5-zA8D0Co0j1eIeer0,4141
1532
1535
  vellum/workflows/expressions/and_.py,sha256=I7lNqrUM3-m_5hmjjiMhaHhJtKcLj39kEFVWPDOqwfo,916
1533
1536
  vellum/workflows/expressions/begins_with.py,sha256=FnWsQXbENm0ZwkfEP7dR8Qx4_MMrzj6C1yqAV2KaNHw,1123
1534
1537
  vellum/workflows/expressions/between.py,sha256=dVeddT6YA91eOAlE1Utg7C7gnCiYE7WP-dg17yXUeAY,1492
@@ -1559,7 +1562,7 @@ vellum/workflows/expressions/not_in.py,sha256=pFvwkFPsn3WJw61ssFgM2U1dqWEeglfz4F
1559
1562
  vellum/workflows/expressions/or_.py,sha256=s-8YdMSSCDS2yijR38kguwok3iqmDMMgDYKV93b4O4s,914
1560
1563
  vellum/workflows/expressions/parse_json.py,sha256=xsk6j3HF7bU1yF6fwt5P9Ugcyd5D9ZXrdng11FRilUI,1088
1561
1564
  vellum/workflows/expressions/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1562
- vellum/workflows/expressions/tests/test_accessor.py,sha256=ijmGjS1pipdurAgYGmfV8Gcle4HIJ5lQHVG18xHjNiQ,5839
1565
+ vellum/workflows/expressions/tests/test_accessor.py,sha256=g2z0mJjuWwVKeXS0yGoFW-aRmT5n_LrhfuBorSmj9kI,7585
1563
1566
  vellum/workflows/expressions/tests/test_expressions.py,sha256=3b6k8xs-CItBBw95NygFLUNoNPKxI4VA1GyWbkMtqyI,11623
1564
1567
  vellum/workflows/expressions/tests/test_parse_json.py,sha256=zpB_qE5_EwWQL7ULQUJm0o1PRSfWZdAqZNW6Ah13oJE,1059
1565
1568
  vellum/workflows/graph/__init__.py,sha256=3sHlay5d_-uD7j3QJXiGl0WHFZZ_QScRvgyDhN2GhHY,74
@@ -1674,7 +1677,7 @@ vellum/workflows/nodes/experimental/tool_calling_node/node.py,sha256=jwL1sbitmm1
1674
1677
  vellum/workflows/nodes/experimental/tool_calling_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1675
1678
  vellum/workflows/nodes/experimental/tool_calling_node/tests/test_node.py,sha256=XK1H_QAT_nVFmFP442RYyPvpTfSgtU6kSGu3-OQPBNU,5072
1676
1679
  vellum/workflows/nodes/experimental/tool_calling_node/tests/test_utils.py,sha256=-g90SdXscuikF7JP0lFGvSvPc8jl2vBuHwBeiYJIiXk,1719
1677
- vellum/workflows/nodes/experimental/tool_calling_node/utils.py,sha256=U5JjMXg_NV_5XavydhOhsS4_EUoQ42KlEVBe_JiSR4g,12683
1680
+ vellum/workflows/nodes/experimental/tool_calling_node/utils.py,sha256=t18ye2wY9jtTjKXJs8oChNGI5xCdxlUUyVYbRJfJLFI,12959
1678
1681
  vellum/workflows/nodes/mocks.py,sha256=a1FjWEIocseMfjzM-i8DNozpUsaW0IONRpZmXBoWlyc,10455
1679
1682
  vellum/workflows/nodes/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1680
1683
  vellum/workflows/nodes/tests/test_mocks.py,sha256=mfPvrs75PKcsNsbJLQAN6PDFoVqs9TmQxpdyFKDdO60,7837
@@ -1707,7 +1710,7 @@ vellum/workflows/sandbox.py,sha256=GVJzVjMuYzOBnSrboB0_6MMRZWBluAyQ2o7syeaeBd0,2
1707
1710
  vellum/workflows/state/__init__.py,sha256=yUUdR-_Vl7UiixNDYQZ-GEM_kJI9dnOia75TtuNEsnE,60
1708
1711
  vellum/workflows/state/base.py,sha256=WIMJYyuHUrP4zt0Nudk66HAK1L6GgGmsU_GQp7BGE2U,22189
1709
1712
  vellum/workflows/state/context.py,sha256=KOAI1wEGn8dGmhmAemJaf4SZbitP3jpIBcwKfznQaRE,3076
1710
- vellum/workflows/state/encoder.py,sha256=I21qwYW3edIqlp78jdbjQgtou0hXYKvmofF-5_BCIlU,2552
1713
+ vellum/workflows/state/encoder.py,sha256=xtKpDAR5qWbxIN61dz3X_5_D47MTrbvvas8n15jys18,2881
1711
1714
  vellum/workflows/state/store.py,sha256=uVe-oN73KwGV6M6YLhwZMMUQhzTQomsVfVnb8V91gVo,1147
1712
1715
  vellum/workflows/state/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1713
1716
  vellum/workflows/state/tests/test_state.py,sha256=YOiC9qZAzkdiqb7nRarNWeDwxo7xHv3y3czlHl81ezg,6741
@@ -1723,7 +1726,7 @@ vellum/workflows/types/stack.py,sha256=h7NE0vXR7l9DevFBIzIAk1Zh59K-kECQtDTKOUunw
1723
1726
  vellum/workflows/types/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1724
1727
  vellum/workflows/types/tests/test_definition.py,sha256=5wh_WEnE51epkoo-4PE-JbPlg8OGJUNlaBVWa9TcNSw,993
1725
1728
  vellum/workflows/types/tests/test_utils.py,sha256=UnZog59tR577mVwqZRqqWn2fScoOU1H6up0EzS8zYhw,2536
1726
- vellum/workflows/types/utils.py,sha256=axxHbPLsnjhEOnMZrc5YarFd-P2bnsacBDQGNCvY8OY,6367
1729
+ vellum/workflows/types/utils.py,sha256=mTctHITBybpt4855x32oCKALBEcMNLn-9cCmfEKgJHQ,6498
1727
1730
  vellum/workflows/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1728
1731
  vellum/workflows/utils/functions.py,sha256=ZN0rrIBF4R_KNt1CbRPVNGR36xEMUa1T7FkgZioou-Y,7185
1729
1732
  vellum/workflows/utils/names.py,sha256=QLUqfJ1tmSEeUwBKTTiv_Qk3QGbInC2RSmlXfGXc8Wo,380
@@ -1734,7 +1737,7 @@ vellum/workflows/utils/tests/test_names.py,sha256=aOqpyvMsOEK_9mg_-yaNxQDW7QQfwq
1734
1737
  vellum/workflows/utils/tests/test_uuids.py,sha256=i77ABQ0M3S-aFLzDXHJq_yr5FPkJEWCMBn1HJ3DObrE,437
1735
1738
  vellum/workflows/utils/tests/test_vellum_variables.py,sha256=vbnKgm41aB5OXlO-ZIPbhQ6xDiZkT8KMxCLqz4zocWY,1791
1736
1739
  vellum/workflows/utils/uuids.py,sha256=DFzPv9RCvsKhvdTEIQyfSek2A31D6S_QcmeLPbgrgTY,739
1737
- vellum/workflows/utils/vellum_variables.py,sha256=tDWGyE8CfxYaCQQfMwTHqQNgK5V5sJMuhjLsliT8Ar4,4286
1740
+ vellum/workflows/utils/vellum_variables.py,sha256=zVzZSRWKV64fmu9MaoEVebW9r8UsXPvRPMvOuBmwI24,5307
1738
1741
  vellum/workflows/vellum_client.py,sha256=xkfoucodxNK5JR2-lbRqZx3xzDgExWkP6kySrpi_Ubc,1079
1739
1742
  vellum/workflows/workflows/__init__.py,sha256=KY45TqvavCCvXIkyCFMEc0dc6jTMOUci93U2DUrlZYc,66
1740
1743
  vellum/workflows/workflows/base.py,sha256=ehJSHDf1vuNjJtKryqKgb5HKGtx_D-wWUiJNBWZ50JU,24347
@@ -1742,8 +1745,8 @@ vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnad
1742
1745
  vellum/workflows/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1743
1746
  vellum/workflows/workflows/tests/test_base_workflow.py,sha256=fROqff6AZpCIzaSwOKSdtYy4XR0UZQ6ejxL3RJOSJVs,20447
1744
1747
  vellum/workflows/workflows/tests/test_context.py,sha256=VJBUcyWVtMa_lE5KxdhgMu0WYNYnUQUDvTF7qm89hJ0,2333
1745
- vellum_ai-0.14.77.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1746
- vellum_ai-0.14.77.dist-info/METADATA,sha256=6DQyChVvOW8sRMyNEo1bB9d073wwWqAovQzhVZjigiU,5556
1747
- vellum_ai-0.14.77.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1748
- vellum_ai-0.14.77.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1749
- vellum_ai-0.14.77.dist-info/RECORD,,
1748
+ vellum_ai-0.14.79.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1749
+ vellum_ai-0.14.79.dist-info/METADATA,sha256=UodF9npSWC-UMqf_F0L-rKwUk-q97JFdxaojQo7pF-8,5556
1750
+ vellum_ai-0.14.79.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1751
+ vellum_ai-0.14.79.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1752
+ vellum_ai-0.14.79.dist-info/RECORD,,
vellum_cli/__init__.py CHANGED
@@ -67,7 +67,7 @@ with the provided module or be available for use. The Workflow Sandbox must also
67
67
  @click.option("--deployment-label", type=str, help="Label to use for the Deployment")
68
68
  @click.option("--deployment-name", type=str, help="Unique name for the Deployment")
69
69
  @click.option("--deployment-description", type=str, help="Description for the Deployment")
70
- @click.option("--release-tag", type=list, help="Release Tag for the Deployment", multiple=True)
70
+ @click.option("--release-tag", help="Release Tag for the Deployment", multiple=True)
71
71
  @click.option(
72
72
  "--dry-run",
73
73
  is_flag=True,
@@ -117,7 +117,7 @@ def workflows_push(
117
117
  @click.option("--deployment-label", type=str, help="Label to use for the Deployment")
118
118
  @click.option("--deployment-name", type=str, help="Unique name for the Deployment")
119
119
  @click.option("--deployment-description", type=str, help="Description for the Deployment")
120
- @click.option("--release-tag", type=list, help="Release Tag for the Deployment", multiple=True)
120
+ @click.option("--release-tag", help="Release Tag for the Deployment", multiple=True)
121
121
  @click.option(
122
122
  "--dry-run",
123
123
  is_flag=True,
vellum_cli/push.py CHANGED
@@ -8,6 +8,7 @@ from uuid import UUID
8
8
  from typing import List, Optional
9
9
 
10
10
  from dotenv import load_dotenv
11
+ from pydantic import ValidationError
11
12
 
12
13
  from vellum.client.core.api_error import ApiError
13
14
  from vellum.resources.workflows.client import OMIT
@@ -129,12 +130,26 @@ def push_command(
129
130
  workflow_config.deployments[0] if workflow_config.deployments else WorkflowDeploymentConfig()
130
131
  )
131
132
 
132
- deployment_config = WorkflowPushDeploymentConfigRequest(
133
- label=deployment_label or cli_deployment_config.label,
134
- name=deployment_name or cli_deployment_config.name,
135
- description=deployment_description or cli_deployment_config.description,
136
- release_tags=release_tags or cli_deployment_config.release_tags,
137
- )
133
+ try:
134
+ deployment_config = WorkflowPushDeploymentConfigRequest(
135
+ label=deployment_label or cli_deployment_config.label,
136
+ name=deployment_name or cli_deployment_config.name,
137
+ description=deployment_description or cli_deployment_config.description,
138
+ release_tags=release_tags or cli_deployment_config.release_tags,
139
+ )
140
+ except ValidationError as e:
141
+ for error in e.errors():
142
+ if "release_tags" in str(error.get("loc", [])):
143
+ handle_cli_error(
144
+ logger,
145
+ title="Invalid release tag format",
146
+ message="Release tags must be provided as separate arguments. "
147
+ "Use: --release-tag tag1 --release-tag tag2",
148
+ )
149
+ return
150
+
151
+ # Re-raise if it's not a release_tags validation error
152
+ raise e
138
153
 
139
154
  # We should check with fern if we could auto-serialize typed fields for us
140
155
  # https://app.shortcut.com/vellum/story/5568
@@ -979,3 +979,63 @@ def test_push__use_default_workspace_if_not_specified__multiple_workflows_config
979
979
  config = configs[0]
980
980
  assert config["workflow_sandbox_id"] == workflow_sandbox_id
981
981
  assert config["workspace"] == "default"
982
+
983
+
984
+ def test_push__deploy_with_malformed_release_tags_shows_friendly_validation_error(mock_module, vellum_client):
985
+ # GIVEN a single workflow configured
986
+ temp_dir = mock_module.temp_dir
987
+ module = mock_module.module
988
+
989
+ # AND a workflow exists in the module successfully
990
+ _ensure_workflow_py(temp_dir, module)
991
+
992
+ # AND the push API call would return successfully
993
+ vellum_client.workflows.push.return_value = WorkflowPushResponse(
994
+ workflow_sandbox_id=str(uuid4()),
995
+ )
996
+
997
+ # WHEN calling `vellum workflows push` with --deploy and --release-tag
998
+ runner = CliRunner()
999
+ result = runner.invoke(cli_main, ["workflows", "push", module, "--deploy", "--release-tag", None]) # type: ignore
1000
+
1001
+ # THEN it should show the friendly error message instead of a raw Pydantic traceback
1002
+ assert "Invalid release tag format" in result.output
1003
+ assert "Release tags must be provided as separate arguments" in result.output
1004
+ assert "--release-tag tag1 --release-tag tag2" in result.output
1005
+
1006
+
1007
+ @pytest.mark.usefixtures("info_log_level")
1008
+ def test_push__deploy_with_release_tags_success(mock_module, vellum_client):
1009
+ # GIVEN a single workflow configured
1010
+ temp_dir = mock_module.temp_dir
1011
+ module = mock_module.module
1012
+
1013
+ # AND a workflow exists in the module successfully
1014
+ _ensure_workflow_py(temp_dir, module)
1015
+
1016
+ # AND the push API call returns successfully
1017
+ workflow_deployment_id = str(uuid4())
1018
+ vellum_client.workflows.push.return_value = WorkflowPushResponse(
1019
+ workflow_sandbox_id=str(uuid4()),
1020
+ workflow_deployment_id=workflow_deployment_id,
1021
+ )
1022
+
1023
+ # WHEN calling `vellum workflows push` with --deploy and --release-tag
1024
+ runner = CliRunner()
1025
+ result = runner.invoke(cli_main, ["workflows", "push", module, "--deploy", "--release-tag", "v1.0.0"])
1026
+
1027
+ # THEN it should succeed
1028
+ assert result.exit_code == 0, result.output
1029
+
1030
+ # AND we should have called the push API with the correct deployment config
1031
+ vellum_client.workflows.push.assert_called_once()
1032
+ call_args = vellum_client.workflows.push.call_args.kwargs
1033
+
1034
+ # AND the deployment_config should contain the release tags
1035
+ deployment_config_str = call_args["deployment_config"]
1036
+ deployment_config = json.loads(deployment_config_str)
1037
+ assert deployment_config["release_tags"] == ["v1.0.0"]
1038
+
1039
+ # AND should show success message
1040
+ assert "Successfully pushed" in result.output
1041
+ assert "Updated vellum.lock.json file." in result.output
@@ -6,7 +6,7 @@ from typing import Any, Callable, Dict, Generic, Optional, Type, TypeVar, cast
6
6
  from vellum.workflows.nodes.bases.base import BaseNode
7
7
  from vellum.workflows.nodes.bases.base_adornment_node import BaseAdornmentNode
8
8
  from vellum.workflows.nodes.utils import get_wrapped_node
9
- from vellum.workflows.types.core import JsonArray, JsonObject
9
+ from vellum.workflows.types.core import JsonObject
10
10
  from vellum.workflows.types.utils import get_original_base
11
11
  from vellum.workflows.utils.uuids import uuid4_from_hash
12
12
  from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
@@ -94,8 +94,8 @@ class BaseAdornmentNodeDisplay(BaseNodeDisplay[_BaseAdornmentNodeType], Generic[
94
94
  additional_kwargs = get_additional_kwargs(wrapped_node_display.node_id) if get_additional_kwargs else {}
95
95
  serialized_wrapped_node = wrapped_node_display.serialize(display_context, **kwargs, **additional_kwargs)
96
96
 
97
- adornments = cast(JsonArray, serialized_wrapped_node.get("adornments")) or []
98
- serialized_wrapped_node["adornments"] = adornments + [adornment] if adornment else adornments
97
+ adornments = cast(list, serialized_wrapped_node.get("adornments")) or []
98
+ serialized_wrapped_node["adornments"] = [adornment] + adornments if adornment else adornments
99
99
 
100
100
  return serialized_wrapped_node
101
101
 
@@ -139,8 +139,8 @@ def test_serialize_node__function_configs():
139
139
  "foo": {
140
140
  "runtime": "PYTHON_3_11_6",
141
141
  "packages": [
142
- CodeExecutionPackage(name="first_package", version="1.0.0"),
143
- CodeExecutionPackage(name="second_package", version="2.0.0"),
142
+ CodeExecutionPackage(name="first_package", version="1.0.0", repository="test-repo"),
143
+ CodeExecutionPackage(name="second_package", version="2.0.0", repository="test-repo"),
144
144
  ],
145
145
  },
146
146
  "bar": {
@@ -179,11 +179,14 @@ def test_serialize_node__function_configs():
179
179
  "foo": {
180
180
  "runtime": "PYTHON_3_11_6",
181
181
  "packages": [
182
- {"version": "1.0.0", "name": "first_package"},
183
- {"version": "2.0.0", "name": "second_package"},
182
+ {"version": "1.0.0", "name": "first_package", "repository": "test-repo"},
183
+ {"version": "2.0.0", "name": "second_package", "repository": "test-repo"},
184
184
  ],
185
185
  },
186
- "bar": {"runtime": "PYTHON_3_11_6", "packages": [{"version": "3.0.0", "name": "third_package"}]},
186
+ "bar": {
187
+ "runtime": "PYTHON_3_11_6",
188
+ "packages": [{"version": "3.0.0", "name": "third_package", "repository": None}],
189
+ },
187
190
  },
188
191
  },
189
192
  },
@@ -1,4 +1,5 @@
1
1
  from uuid import uuid4
2
+ from typing import Any, Dict, List, cast
2
3
 
3
4
  from deepdiff import DeepDiff
4
5
 
@@ -269,6 +270,21 @@ def test_serialize_node__stacked():
269
270
  },
270
271
  "ports": [{"id": "408cd5fb-3a3e-4eb2-9889-61111bd6a129", "name": "default", "type": "DEFAULT"}],
271
272
  "adornments": [
273
+ {
274
+ "id": "3344083c-a32c-4a32-920b-0fb5093448fa",
275
+ "label": "TryNode",
276
+ "base": {
277
+ "name": "TryNode",
278
+ "module": ["vellum", "workflows", "nodes", "core", "try_node", "node"],
279
+ },
280
+ "attributes": [
281
+ {
282
+ "id": "ab2fbab0-e2a0-419b-b1ef-ce11ecf11e90",
283
+ "name": "on_error_code",
284
+ "value": {"type": "CONSTANT_VALUE", "value": {"type": "JSON", "value": None}},
285
+ }
286
+ ],
287
+ },
272
288
  {
273
289
  "id": "5be7d260-74f7-4734-b31b-a46a94539586",
274
290
  "label": "RetryNode",
@@ -299,24 +315,41 @@ def test_serialize_node__stacked():
299
315
  },
300
316
  ],
301
317
  },
302
- {
303
- "id": "3344083c-a32c-4a32-920b-0fb5093448fa",
304
- "label": "TryNode",
305
- "base": {
306
- "name": "TryNode",
307
- "module": ["vellum", "workflows", "nodes", "core", "try_node", "node"],
308
- },
309
- "attributes": [
310
- {
311
- "id": "ab2fbab0-e2a0-419b-b1ef-ce11ecf11e90",
312
- "name": "on_error_code",
313
- "value": {"type": "CONSTANT_VALUE", "value": {"type": "JSON", "value": None}},
314
- }
315
- ],
316
- },
317
318
  ],
318
319
  "attributes": [],
319
320
  "outputs": [],
320
321
  },
321
322
  inner_stacked_generic_node,
322
323
  )
324
+
325
+
326
+ def test_serialize_node__adornment_order_matches_decorator_order():
327
+ """
328
+ Tests that adornments are serialized in the same order as decorators are applied.
329
+ """
330
+
331
+ @TryNode.wrap()
332
+ @RetryNode.wrap(max_attempts=3)
333
+ class MyNode(BaseNode):
334
+ pass
335
+
336
+ # AND a workflow that uses the decorated node
337
+ class MyWorkflow(BaseWorkflow):
338
+ graph = MyNode
339
+
340
+ # WHEN we serialize the workflow
341
+ workflow_display = get_workflow_display(workflow_class=MyWorkflow)
342
+ exec_config = cast(Dict[str, Any], workflow_display.serialize())
343
+
344
+ # THEN the workflow should serialize successfully
345
+ assert isinstance(exec_config["workflow_raw_data"], dict)
346
+ assert isinstance(exec_config["workflow_raw_data"]["nodes"], list)
347
+
348
+ # AND we should find our decorated node
349
+ nodes = cast(List[Dict[str, Any]], exec_config["workflow_raw_data"]["nodes"])
350
+ my_node = [node for node in nodes if isinstance(node, dict) and node["type"] == "GENERIC"][0]
351
+
352
+ adornments = cast(List[Dict[str, Any]], my_node["adornments"])
353
+ assert len(adornments) == 2
354
+ assert adornments[0]["label"] == "TryNode"
355
+ assert adornments[1]["label"] == "RetryNode"
@@ -1,6 +1,9 @@
1
+ from typing import List
2
+
1
3
  from deepdiff import DeepDiff
2
4
 
3
5
  from vellum import ChatMessagePromptBlock, FunctionDefinition, JinjaPromptBlock
6
+ from vellum.client.types.chat_message import ChatMessage
4
7
  from vellum.workflows import BaseWorkflow
5
8
  from vellum.workflows.inputs import BaseInputs
6
9
  from vellum.workflows.nodes import InlinePromptNode
@@ -554,3 +557,52 @@ def test_serialize_workflow_with_nested_descriptor_blocks():
554
557
  "type": "DICTIONARY_REFERENCE",
555
558
  }
556
559
  ]
560
+
561
+
562
+ def test_inline_prompt_node__coalesce_expression_serialization():
563
+ """
564
+ Tests that prompt nodes can serialize coalesce expressions like State.chat_history.coalesce([]).
565
+ """
566
+
567
+ # GIVEN a custom state with chat_history
568
+ class MyState(BaseState):
569
+ chat_history: List[ChatMessage] = []
570
+
571
+ # AND a prompt node that uses a coalesce expression as input
572
+ class MyNode(InlinePromptNode[MyState]):
573
+ ml_model = "gpt-4o"
574
+ blocks = []
575
+ prompt_inputs = {
576
+ "chat_history": MyState.chat_history.coalesce([]),
577
+ }
578
+
579
+ class TestWorkflow(BaseWorkflow[BaseInputs, MyState]):
580
+ graph = MyNode
581
+
582
+ # WHEN the node is serialized
583
+ workflow_display = get_workflow_display(workflow_class=TestWorkflow)
584
+ serialized: dict = workflow_display.serialize()
585
+
586
+ # THEN the prompt is serialized with the correct inputs
587
+ prompt_nodes = [node for node in serialized["workflow_raw_data"]["nodes"] if node["type"] == "PROMPT"]
588
+ prompt_node = prompt_nodes[0]
589
+
590
+ prompt_inputs_attr = next((attr for attr in prompt_node["attributes"] if attr["name"] == "prompt_inputs"), None)
591
+ assert prompt_inputs_attr
592
+ assert prompt_inputs_attr["value"]["type"] == "DICTIONARY_REFERENCE"
593
+ chat_history_entry = prompt_inputs_attr["value"]["entries"][0]
594
+
595
+ assert chat_history_entry["key"] == "chat_history"
596
+ assert chat_history_entry["value"]["type"] == "BINARY_EXPRESSION"
597
+ assert chat_history_entry["value"]["operator"] == "coalesce"
598
+ assert chat_history_entry["value"]["lhs"] == {
599
+ "type": "WORKFLOW_STATE",
600
+ "state_variable_id": "6012a4f7-a8ff-464d-bd62-7c41fde06fa4",
601
+ }
602
+ assert chat_history_entry["value"]["rhs"] == {
603
+ "type": "CONSTANT_VALUE",
604
+ "value": {
605
+ "type": "JSON",
606
+ "value": [],
607
+ },
608
+ }
@@ -146,7 +146,7 @@ def test_serialize_workflow():
146
146
  "forced": None,
147
147
  "strict": None,
148
148
  },
149
- "src": 'def get_current_weather(location: str, unit: str) -> str:\n """\n Get the current weather in a given location.\n """\n return f"The current weather in {location} is sunny with a temperature of 70 degrees {unit}."\n', # noqa: E501
149
+ "src": 'import math\n\n\ndef get_current_weather(location: str, unit: str) -> str:\n """\n Get the current weather in a given location.\n """\n return f"The current weather in {location} is sunny with a temperature of {get_temperature(70.1)} degrees {unit}."\n\n\ndef get_temperature(temperature: float) -> int:\n """\n Get the temperature in a given location.\n """\n return math.floor(temperature)\n', # noqa: E501
150
150
  }
151
151
  ],
152
152
  },
@@ -162,7 +162,7 @@ def test_serialize_workflow():
162
162
  "value": {
163
163
  "get_current_weather": {
164
164
  "runtime": "PYTHON_3_11_6",
165
- "packages": [{"version": "2.26.0", "name": "requests"}],
165
+ "packages": [{"version": "2.26.0", "name": "requests", "repository": None}],
166
166
  }
167
167
  },
168
168
  },
@@ -1,5 +1,16 @@
1
+ from datetime import datetime
2
+
1
3
  from deepdiff import DeepDiff
2
4
 
5
+ from vellum.client.types.release_environment import ReleaseEnvironment
6
+ from vellum.client.types.release_release_tag import ReleaseReleaseTag
7
+ from vellum.client.types.release_review_reviewer import ReleaseReviewReviewer
8
+ from vellum.client.types.slim_release_review import SlimReleaseReview
9
+ from vellum.client.types.workflow_deployment_release import WorkflowDeploymentRelease
10
+ from vellum.client.types.workflow_deployment_release_workflow_deployment import (
11
+ WorkflowDeploymentReleaseWorkflowDeployment,
12
+ )
13
+ from vellum.client.types.workflow_deployment_release_workflow_version import WorkflowDeploymentReleaseWorkflowVersion
3
14
  from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
4
15
 
5
16
  from tests.workflows.basic_tool_calling_node_workflow_deployment.workflow import (
@@ -7,7 +18,41 @@ from tests.workflows.basic_tool_calling_node_workflow_deployment.workflow import
7
18
  )
8
19
 
9
20
 
10
- def test_serialize_workflow():
21
+ def test_serialize_workflow(vellum_client):
22
+ vellum_client.release_reviews.retrieve_workflow_deployment_release.return_value = WorkflowDeploymentRelease(
23
+ id="test-id",
24
+ created=datetime.now(),
25
+ environment=ReleaseEnvironment(
26
+ id="test-id",
27
+ name="test-name",
28
+ label="test-label",
29
+ ),
30
+ created_by=None,
31
+ workflow_version=WorkflowDeploymentReleaseWorkflowVersion(
32
+ id="test-id",
33
+ input_variables=[],
34
+ output_variables=[],
35
+ ),
36
+ deployment=WorkflowDeploymentReleaseWorkflowDeployment(name="test-name"),
37
+ description="test-description", # main mock
38
+ release_tags=[
39
+ ReleaseReleaseTag(
40
+ name="test-name",
41
+ source="USER",
42
+ )
43
+ ],
44
+ reviews=[
45
+ SlimReleaseReview(
46
+ id="test-id",
47
+ created=datetime.now(),
48
+ reviewer=ReleaseReviewReviewer(
49
+ id="test-id",
50
+ full_name="test-name",
51
+ ),
52
+ state="APPROVED",
53
+ )
54
+ ],
55
+ )
11
56
  # GIVEN a Workflow that uses a generic node
12
57
  # WHEN we serialize it
13
58
  workflow_display = get_workflow_display(workflow_class=BasicToolCallingNodeWorkflowDeploymentWorkflow)
@@ -51,8 +96,8 @@ def test_serialize_workflow():
51
96
  "value": [
52
97
  {
53
98
  "type": "WORKFLOW_DEPLOYMENT",
54
- "name": "deployment_1",
55
- "description": "Workflow deployment for deployment_1",
99
+ "name": "test-name",
100
+ "description": "test-description",
56
101
  "deployment": "deployment_1",
57
102
  "release_tag": "LATEST",
58
103
  }
@@ -346,14 +346,20 @@ def serialize_value(display_context: "WorkflowDisplayContext", value: Any) -> Js
346
346
  }
347
347
 
348
348
  if isinstance(value, DeploymentDefinition):
349
+ workflow_deployment_release = display_context.client.release_reviews.retrieve_workflow_deployment_release(
350
+ value.deployment, value.release_tag
351
+ )
352
+ name = workflow_deployment_release.deployment.name or value.deployment
353
+ description = workflow_deployment_release.description or f"Workflow Deployment for {name}"
354
+
349
355
  return {
350
356
  "type": "CONSTANT_VALUE",
351
357
  "value": {
352
358
  "type": "JSON",
353
359
  "value": {
354
360
  "type": "WORKFLOW_DEPLOYMENT",
355
- "name": value.deployment,
356
- "description": f"Workflow deployment for {value.deployment}",
361
+ "name": name,
362
+ "description": description,
357
363
  "deployment": value.deployment,
358
364
  "release_tag": value.release_tag,
359
365
  },