vellum-ai 0.14.0__py3-none-any.whl → 0.14.1__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 (40) hide show
  1. vellum/client/core/client_wrapper.py +1 -1
  2. vellum/prompts/blocks/compilation.py +23 -16
  3. vellum/prompts/blocks/tests/test_compilation.py +29 -0
  4. vellum/utils/templating/render.py +2 -0
  5. vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py +39 -1
  6. vellum/workflows/nodes/utils.py +9 -1
  7. vellum/workflows/state/base.py +21 -1
  8. {vellum_ai-0.14.0.dist-info → vellum_ai-0.14.1.dist-info}/METADATA +1 -1
  9. {vellum_ai-0.14.0.dist-info → vellum_ai-0.14.1.dist-info}/RECORD +40 -37
  10. vellum_ee/workflows/display/base.py +14 -0
  11. vellum_ee/workflows/display/nodes/base_node_display.py +11 -22
  12. vellum_ee/workflows/display/nodes/vellum/tests/test_prompt_node.py +52 -0
  13. vellum_ee/workflows/display/tests/test_vellum_workflow_display.py +1 -0
  14. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py +4 -1
  15. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py +1 -0
  16. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +3 -0
  17. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +4 -0
  18. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_default_state_serialization.py +243 -0
  19. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py +1 -0
  20. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py +1 -0
  21. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py +1 -1
  22. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +1 -0
  23. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +1 -0
  24. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +1 -0
  25. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py +1 -0
  26. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_serialization.py +1 -1
  27. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py +1 -0
  28. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py +1 -0
  29. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py +1 -0
  30. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py +1 -0
  31. vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py +1 -0
  32. vellum_ee/workflows/display/types.py +5 -1
  33. vellum_ee/workflows/display/utils/expressions.py +26 -0
  34. vellum_ee/workflows/display/utils/vellum.py +5 -0
  35. vellum_ee/workflows/display/vellum.py +14 -0
  36. vellum_ee/workflows/display/workflows/base_workflow_display.py +30 -1
  37. vellum_ee/workflows/display/workflows/vellum_workflow_display.py +41 -0
  38. {vellum_ai-0.14.0.dist-info → vellum_ai-0.14.1.dist-info}/LICENSE +0 -0
  39. {vellum_ai-0.14.0.dist-info → vellum_ai-0.14.1.dist-info}/WHEEL +0 -0
  40. {vellum_ai-0.14.0.dist-info → vellum_ai-0.14.1.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.0",
21
+ "X-Fern-SDK-Version": "0.14.1",
22
22
  }
23
23
  headers["X_API_KEY"] = self.api_key
24
24
  return headers
@@ -1,5 +1,5 @@
1
1
  import json
2
- from typing import Optional, cast
2
+ from typing import Sequence, Union, cast
3
3
 
4
4
  from vellum import (
5
5
  ChatMessage,
@@ -14,6 +14,7 @@ from vellum.client.types.audio_vellum_value import AudioVellumValue
14
14
  from vellum.client.types.function_call import FunctionCall
15
15
  from vellum.client.types.function_call_vellum_value import FunctionCallVellumValue
16
16
  from vellum.client.types.image_vellum_value import ImageVellumValue
17
+ from vellum.client.types.number_input import NumberInput
17
18
  from vellum.client.types.vellum_audio import VellumAudio
18
19
  from vellum.client.types.vellum_image import VellumImage
19
20
  from vellum.prompts.blocks.exceptions import PromptCompilationError
@@ -22,15 +23,20 @@ from vellum.utils.templating.constants import DEFAULT_JINJA_CUSTOM_FILTERS
22
23
  from vellum.utils.templating.render import render_sandboxed_jinja_template
23
24
  from vellum.utils.typing import cast_not_optional
24
25
 
26
+ PromptInput = Union[PromptRequestInput, NumberInput]
27
+
25
28
 
26
29
  def compile_prompt_blocks(
27
30
  blocks: list[PromptBlock],
28
- inputs: list[PromptRequestInput],
31
+ inputs: Sequence[PromptInput],
29
32
  input_variables: list[VellumVariable],
30
33
  ) -> list[CompiledPromptBlock]:
31
34
  """Compiles a list of Prompt Blocks, performing all variable substitutions and Jinja templating needed."""
32
35
 
33
36
  sanitized_inputs = _sanitize_inputs(inputs)
37
+ inputs_by_name = {
38
+ (input_.name if isinstance(input_, NumberInput) else input_.key): input_ for input_ in sanitized_inputs
39
+ }
34
40
 
35
41
  compiled_blocks: list[CompiledPromptBlock] = []
36
42
  for block in blocks:
@@ -66,7 +72,7 @@ def compile_prompt_blocks(
66
72
 
67
73
  rendered_template = render_sandboxed_jinja_template(
68
74
  template=block.template,
69
- input_values={input_.key: input_.value for input_ in sanitized_inputs},
75
+ input_values={name: inp.value for name, inp in inputs_by_name.items()},
70
76
  jinja_custom_filters=DEFAULT_JINJA_CUSTOM_FILTERS,
71
77
  jinja_globals=DEFAULT_JINJA_CUSTOM_FILTERS,
72
78
  )
@@ -80,9 +86,7 @@ def compile_prompt_blocks(
80
86
  )
81
87
 
82
88
  elif block.block_type == "VARIABLE":
83
- compiled_input: Optional[PromptRequestInput] = next(
84
- (input_ for input_ in sanitized_inputs if input_.key == str(block.input_variable)), None
85
- )
89
+ compiled_input = inputs_by_name.get(block.input_variable)
86
90
  if compiled_input is None:
87
91
  raise PromptCompilationError(f"Input variable '{block.input_variable}' not found")
88
92
 
@@ -196,23 +200,26 @@ def _compile_chat_messages_as_prompt_blocks(chat_messages: list[ChatMessage]) ->
196
200
 
197
201
  def _compile_rich_text_block_as_value_block(
198
202
  block: RichTextPromptBlock,
199
- inputs: list[PromptRequestInput],
203
+ inputs: list[PromptInput],
200
204
  ) -> CompiledValuePromptBlock:
201
205
  value: str = ""
206
+ inputs_by_name = {(input_.name if isinstance(input_, NumberInput) else input_.key): input_ for input_ in inputs}
202
207
  for child_block in block.blocks:
203
208
  if child_block.block_type == "PLAIN_TEXT":
204
209
  value += child_block.text
205
210
  elif child_block.block_type == "VARIABLE":
206
- variable = next((input_ for input_ in inputs if input_.key == str(child_block.input_variable)), None)
207
- if variable is None:
211
+ input = inputs_by_name.get(child_block.input_variable)
212
+ if input is None:
208
213
  raise PromptCompilationError(f"Input variable '{child_block.input_variable}' not found")
209
- elif variable.type == "STRING":
210
- value += str(variable.value)
211
- elif variable.type == "JSON":
212
- value += json.dumps(variable.value, indent=4)
214
+ elif input.type == "STRING":
215
+ value += str(input.value)
216
+ elif input.type == "JSON":
217
+ value += json.dumps(input.value, indent=4)
218
+ elif input.type == "NUMBER":
219
+ value += str(input.value)
213
220
  else:
214
221
  raise PromptCompilationError(
215
- f"Input variable '{child_block.input_variable}' must be of type STRING or JSON"
222
+ f"Input variable '{child_block.input_variable}' has an invalid type: {input.type}"
216
223
  )
217
224
  else:
218
225
  raise PromptCompilationError(f"Invalid child block_type for RICH_TEXT: {child_block.block_type}")
@@ -220,8 +227,8 @@ def _compile_rich_text_block_as_value_block(
220
227
  return CompiledValuePromptBlock(content=StringVellumValue(value=value), cache_config=block.cache_config)
221
228
 
222
229
 
223
- def _sanitize_inputs(inputs: list[PromptRequestInput]) -> list[PromptRequestInput]:
224
- sanitized_inputs: list[PromptRequestInput] = []
230
+ def _sanitize_inputs(inputs: Sequence[PromptInput]) -> list[PromptInput]:
231
+ sanitized_inputs: list[PromptInput] = []
225
232
  for input_ in inputs:
226
233
  if input_.type == "CHAT_HISTORY" and input_.value is None:
227
234
  sanitized_inputs.append(input_.model_copy(update={"value": cast(list[ChatMessage], [])}))
@@ -10,6 +10,7 @@ from vellum import (
10
10
  VariablePromptBlock,
11
11
  VellumVariable,
12
12
  )
13
+ from vellum.client.types.number_input import NumberInput
13
14
  from vellum.prompts.blocks.compilation import compile_prompt_blocks
14
15
  from vellum.prompts.blocks.types import CompiledChatMessagePromptBlock, CompiledValuePromptBlock
15
16
 
@@ -94,6 +95,33 @@ from vellum.prompts.blocks.types import CompiledChatMessagePromptBlock, Compiled
94
95
  ),
95
96
  ],
96
97
  ),
98
+ (
99
+ [
100
+ ChatMessagePromptBlock(
101
+ chat_role="USER",
102
+ blocks=[
103
+ RichTextPromptBlock(
104
+ blocks=[
105
+ PlainTextPromptBlock(text="Count to "),
106
+ VariablePromptBlock(input_variable="count"),
107
+ ]
108
+ )
109
+ ],
110
+ )
111
+ ],
112
+ [
113
+ # TODO: We don't yet have PromptRequestNumberInput. We should either add it or migrate
114
+ # Prompts to using these more generic inputs.
115
+ NumberInput(name="count", value=10),
116
+ ],
117
+ [VellumVariable(id="901ec2d6-430c-4341-b963-ca689006f5cc", type="NUMBER", key="count")],
118
+ [
119
+ CompiledChatMessagePromptBlock(
120
+ role="USER",
121
+ blocks=[CompiledValuePromptBlock(content=StringVellumValue(value="Count to 10.0"))],
122
+ ),
123
+ ],
124
+ ),
97
125
  ],
98
126
  ids=[
99
127
  "empty",
@@ -102,6 +130,7 @@ from vellum.prompts.blocks.types import CompiledChatMessagePromptBlock, Compiled
102
130
  "rich-text-no-variables",
103
131
  "rich-text-with-variables",
104
132
  "chat-message",
133
+ "number-input",
105
134
  ],
106
135
  )
107
136
  def test_compile_prompt_blocks__happy(blocks, inputs, input_variables, expected):
@@ -42,6 +42,8 @@ def render_sandboxed_jinja_template(
42
42
 
43
43
  rendered_template = jinja_template.render(input_values)
44
44
  except json.JSONDecodeError as e:
45
+ if not e.doc:
46
+ raise JinjaTemplateError("Unable to render jinja template:\n" "Cannot run json.loads() on empty input")
45
47
  if e.msg == "Invalid control character at":
46
48
  raise JinjaTemplateError(
47
49
  "Unable to render jinja template:\n"
@@ -1,8 +1,10 @@
1
+ import pytest
1
2
  import json
2
- from typing import List
3
+ from typing import List, Union
3
4
 
4
5
  from vellum.client.types.chat_message import ChatMessage
5
6
  from vellum.client.types.function_call import FunctionCall
7
+ from vellum.workflows.exceptions import NodeException
6
8
  from vellum.workflows.nodes.bases.base import BaseNode
7
9
  from vellum.workflows.nodes.core.templating_node.node import TemplatingNode
8
10
  from vellum.workflows.state import BaseState
@@ -155,3 +157,39 @@ def test_templating_node__function_call_output():
155
157
 
156
158
  # THEN the output is the expected function call
157
159
  assert outputs.result == FunctionCall(name="test", arguments={"key": "value"})
160
+
161
+
162
+ def test_templating_node__blank_json_input():
163
+ """Test that templating node properly handles blank JSON input."""
164
+
165
+ # GIVEN a templating node that tries to parse blank JSON
166
+ class BlankJsonTemplateNode(TemplatingNode[BaseState, Json]):
167
+ template = "{{ json.loads(data) }}"
168
+ inputs = {
169
+ "data": "", # Blank input
170
+ }
171
+
172
+ # WHEN the node is run
173
+ node = BlankJsonTemplateNode()
174
+
175
+ # THEN it should raise an appropriate error
176
+ with pytest.raises(NodeException) as exc_info:
177
+ node.run()
178
+
179
+ assert "Unable to render jinja template:\nCannot run json.loads() on empty input" in str(exc_info.value)
180
+
181
+
182
+ def test_templating_node__union_float_int_output():
183
+ # GIVEN a templating node that outputs either a float or an int
184
+ class UnionTemplateNode(TemplatingNode[BaseState, Union[float, int]]):
185
+ template = """{{ obj[\"score\"] | float }}"""
186
+ inputs = {
187
+ "obj": {"score": 42.5},
188
+ }
189
+
190
+ # WHEN the node is run
191
+ node = UnionTemplateNode()
192
+ outputs = node.run()
193
+
194
+ # THEN it should correctly parse as a float
195
+ assert outputs.result == 42.5
@@ -2,7 +2,7 @@ from functools import cache
2
2
  import json
3
3
  import sys
4
4
  from types import ModuleType
5
- from typing import Any, Callable, Optional, Type, TypeVar, get_args, get_origin
5
+ from typing import Any, Callable, Optional, Type, TypeVar, Union, get_args, get_origin
6
6
 
7
7
  from pydantic import BaseModel
8
8
 
@@ -113,6 +113,14 @@ def parse_type_from_str(result_as_str: str, output_type: Any) -> Any:
113
113
  except json.JSONDecodeError:
114
114
  raise ValueError("Invalid JSON format for result_as_str")
115
115
 
116
+ if get_origin(output_type) is Union:
117
+ for inner_type in get_args(output_type):
118
+ try:
119
+ return parse_type_from_str(result_as_str, inner_type)
120
+ except ValueError:
121
+ continue
122
+ raise ValueError(f"Could not parse with any of the Union types: {output_type}")
123
+
116
124
  if issubclass(output_type, BaseModel):
117
125
  try:
118
126
  data = json.loads(result_as_str)
@@ -18,7 +18,13 @@ from vellum.workflows.inputs.base import BaseInputs
18
18
  from vellum.workflows.references import ExternalInputReference, OutputReference, StateValueReference
19
19
  from vellum.workflows.types.generics import StateType
20
20
  from vellum.workflows.types.stack import Stack
21
- from vellum.workflows.types.utils import datetime_now, deepcopy_with_exclusions, get_class_by_qualname, infer_types
21
+ from vellum.workflows.types.utils import (
22
+ datetime_now,
23
+ deepcopy_with_exclusions,
24
+ get_class_attr_names,
25
+ get_class_by_qualname,
26
+ infer_types,
27
+ )
22
28
 
23
29
  if TYPE_CHECKING:
24
30
  from vellum.workflows.nodes.bases import BaseNode
@@ -47,6 +53,20 @@ class _BaseStateMeta(type):
47
53
 
48
54
  return super().__getattribute__(name)
49
55
 
56
+ def __iter__(cls) -> Iterator[StateValueReference]:
57
+ # We iterate through the inheritance hierarchy to find all the StateValueReference attached to this
58
+ # Inputs class. __mro__ is the method resolution order, which is the order in which base classes are resolved.
59
+ for resolved_cls in cls.__mro__:
60
+ attr_names = get_class_attr_names(resolved_cls)
61
+ for attr_name in attr_names:
62
+ if attr_name == "meta":
63
+ continue
64
+ attr_value = getattr(resolved_cls, attr_name)
65
+ if not isinstance(attr_value, (StateValueReference)):
66
+ continue
67
+
68
+ yield attr_value
69
+
50
70
 
51
71
  class _SnapshottableDict(dict, _Snapshottable):
52
72
  def __setitem__(self, key: Any, value: Any) -> None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vellum-ai
3
- Version: 0.14.0
3
+ Version: 0.14.1
4
4
  Summary:
5
5
  License: MIT
6
6
  Requires-Python: >=3.9,<4.0
@@ -19,9 +19,9 @@ vellum_ee/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  vellum_ee/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
20
  vellum_ee/workflows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
21
  vellum_ee/workflows/display/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
- vellum_ee/workflows/display/base.py,sha256=3ZFUYRNKL24fBqXhKpa_Dq2W1a-a86J20dmJYA3H2eY,1755
22
+ vellum_ee/workflows/display/base.py,sha256=i8o7Ex0S9BVub_91s6D2a8kHGcv3ro5XGEwSzeVSz-Y,2083
23
23
  vellum_ee/workflows/display/nodes/__init__.py,sha256=5XOcZJXYUgaLS55QgRJzyQ_W1tpeprjnYAeYVezqoGw,160
24
- vellum_ee/workflows/display/nodes/base_node_display.py,sha256=j5AoStKNjSmSdxKNqJsi_de4Lhi1WmK0IjdXLQFf2oE,16857
24
+ vellum_ee/workflows/display/nodes/base_node_display.py,sha256=En8Ir2e1mpExkAi1T8ExOEpZbv5gu6OetaNq35-_WSY,16317
25
25
  vellum_ee/workflows/display/nodes/base_node_vellum_display.py,sha256=pLO0dORfRu--Ne9NgoyFT_CNjfpr5fGCsgbsMkUF5GM,2845
26
26
  vellum_ee/workflows/display/nodes/get_node_display_class.py,sha256=0S6ksPp53WXWh1RQVH71nj2bkCWBj4ZaFYhTxW3N2F4,1230
27
27
  vellum_ee/workflows/display/nodes/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -47,46 +47,49 @@ vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py,sha256=6
47
47
  vellum_ee/workflows/display/nodes/vellum/templating_node.py,sha256=JVIMPR3WpveOCWZubHKZkE04mavnTdb_9QY_r3XliRg,3424
48
48
  vellum_ee/workflows/display/nodes/vellum/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
49
  vellum_ee/workflows/display/nodes/vellum/tests/test_error_node.py,sha256=ulrpoYUW-5kIxfG4Lf5F2p0k_EoYKhmahEbF3P_eruM,1648
50
+ vellum_ee/workflows/display/nodes/vellum/tests/test_prompt_node.py,sha256=bg9INsXiWfyK047u8TD1oEOFYrqDq8GC7Hvgz69n7BE,1988
50
51
  vellum_ee/workflows/display/nodes/vellum/tests/test_try_node.py,sha256=mtzB8LJlFCHVFM4H5AanLp29gQfaVmnN4A4iaRGJHoI,2427
51
52
  vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py,sha256=3uT7Gbc0f_mQ3u8uZuCWd0mJ4GtWbz2gbUMySYaVlNE,3774
52
53
  vellum_ee/workflows/display/nodes/vellum/try_node.py,sha256=EoU1J7HfcszAZr7ROy_xsNhaDBRiI95-wTK-OzgBwvg,5861
53
54
  vellum_ee/workflows/display/nodes/vellum/utils.py,sha256=OEGHjQSbuUgJexXI1aubYW33z2F_YdkhQ8REahfz864,4320
54
55
  vellum_ee/workflows/display/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
55
- vellum_ee/workflows/display/tests/test_vellum_workflow_display.py,sha256=h4bE187MyM0eT_elFnOxwsCeMHeuzSK0orjgAy8kV1k,4952
56
+ vellum_ee/workflows/display/tests/test_vellum_workflow_display.py,sha256=1EEvkKQRfOKlnpLxE9-hKSsVLLaelM39LY7007LM5dg,4983
56
57
  vellum_ee/workflows/display/tests/workflow_serialization/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
58
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
58
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py,sha256=EenmEdBtHUFQ0OS-kE7Vboax3JnDdj-K4Qixt5oR0Po,2253
59
+ vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py,sha256=A1-tIpC5KIKG9JA_rkd1nLS8zUG3Kb4QiVdvb3boFxE,2509
59
60
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py,sha256=KYdohS5pRgHM0DcUaK0tHa40f0gSvDKi2K5On0zNEU8,8305
60
61
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py,sha256=1cszL6N6FNGVm61MOa7AEiHnF0QjZWqDQuPOp4yiG94,18277
61
62
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py,sha256=-12ZkZb3f5gyoNASV2yeQtMo5HmNsVEo8nXwL6IC-I8,6261
62
63
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py,sha256=6th6kCwzql6lddjkTQx4Jbvvs4ChqtJwctW-B4QuBhI,37352
63
64
  vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py,sha256=EbVgg_3_ipTt3MOop4RARX0fmNjwqZtkhIXzx9nGw7Y,4487
64
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py,sha256=5LQ36vImbVRmLpOdhWKtGmr9pypeZc0HAzIxwQoKtWA,15890
65
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py,sha256=3lmg0bP6QwnHjQCpxz3IiucowmgAcjelHRTE9JRQ9-A,29152
66
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py,sha256=ddk2tx7dFqQ7o2JtRZz2Mv6GHEwjJSF_u-1Zg83q7to,47564
67
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py,sha256=02gG5C0wHbjzuTgVYCsNrtW1kEOeaM_5zXmznaUKzgk,6079
68
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py,sha256=Ah8CxAxAQYnxsNasLB8esN_c9eRDQnmV_aDWC9Kp98s,5746
69
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py,sha256=0xK9TFqPD5Hy65T-iacZ8pjYHD8XkzZXS35rLwof7uc,7427
65
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py,sha256=IRazH2QR6F8RGqNemEnHueyj5DtEa6rFTYhT16S4jI8,15917
66
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py,sha256=PiHqgj-vLhlaOHoQFVVEW2YydYWLI0mX6nq_sbzZiy4,29233
67
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py,sha256=R8DW1DUb0DOSLtnF2E1HaCTmtpG-ski0LfcM2WeLVNo,47672
68
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_default_state_serialization.py,sha256=z9FSufJeV-003R87wi_Lx4mZewdeeOeTPCGNc9vg8vY,8819
69
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py,sha256=wgedEa2IVP2ssH_FLghoEmLgpJR41AY-iNIw1SESeqA,6106
70
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py,sha256=yIq5UexHAk7Afh_6sMlXNAUeKdckBUvCBVIEDLEnhFs,5773
71
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py,sha256=0N7lqB2WMvSItUY78EWpF-g4fXvhkc4NCY-Ws57OYsQ,7446
70
72
  vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_prompt_node_serialization.py,sha256=XRtXTWtNXHe1g8E_mNcAhYZVjc0UcGlJRjq34_sd0jo,787
71
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py,sha256=HEfRYBVwZ6fy0hHhgsgTBEQJJAp_0wsaCJ_OtpZGdqE,20578
72
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py,sha256=L1SrD5KfZjlAVh2BkOe3pCQOstVf_SiqD0KGoZlknU8,16145
73
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py,sha256=ojzdgGb2zGYloOX57V_FyXxjUqOnWMN6z8GUlF8yDMA,8422
74
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py,sha256=SuADagoAr-IWZN5az98axWnXcSrlG6gXV72Q-ThozVU,8622
75
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_serialization.py,sha256=NcpcC9vENF0Z3Vg7b0G0WV7EJScmBKg-JtjQENMKvn0,12989
76
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py,sha256=eQNyiNQG7Cgx0QW_xlN9tQql4D2ak_P2WB-OgMkAVEs,11295
77
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py,sha256=9_mC6-_u3qxJZzkrYrDtzWhpKlnlOD4oXSj8Ztnwet4,7791
78
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py,sha256=1HaEwIbxzWl2OEEVlsNcHFQKMhUKQPlsIMaHnjvMODI,3754
79
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py,sha256=5eKEMwrKT5O8dPsOgQ89iZwzpA304jneimQeT9GlpLk,2428
80
- vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py,sha256=xmKyOKqGRhWUXXbTbCAXX40qINcvK7mjpEfXz0Ny21s,7404
81
- vellum_ee/workflows/display/types.py,sha256=s1w2KELKI2kde4G2M3iniOEdPObNKYgYtr31sAgZqRI,2644
73
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py,sha256=cKM87WUrBZwVauP7VD4rQdObd2jllHJJRHWDGL1tgMI,20605
74
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py,sha256=PbIezAnkGubhY_e5dpOaaaVZ9VeoYJKqvCKbIbjucfU,16172
75
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py,sha256=ObCnoIVJM434jJBC3_kOTKbY4sCDHlknwMTFWRGiOtU,8449
76
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py,sha256=-bGp82C5_XgcVxeM80zWL9viogxvE4DGk7-5H__wwxA,8649
77
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_serialization.py,sha256=elc4ak2OyI4y5P6GPnK2RwuZLcx4FL6hHlmhY3ARk6k,13008
78
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py,sha256=BzFNl9ECeGh0krm-CUjbBQQq0g7krANsp0Sh-j5dAkc,11322
79
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py,sha256=xXtW915v9yxxKlyu5ObzKHyJYMvobvev3ermX61SGx4,7818
80
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py,sha256=NdhE3lm7RMQ8DqkraPSq24IbOxNla9unbs4tsMWRzm4,3781
81
+ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py,sha256=gHKU8Vg960ooV3uXqM2LMnVS-mGbv3aagGozQuTVTjI,2455
82
+ vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py,sha256=huKAOeMJ2MKmp6XtbvMJTUadqynoV40Ypoz9jsBEBEQ,7431
83
+ vellum_ee/workflows/display/types.py,sha256=bm355ZcZ-7WaesBvIB8RbWDD7qiFmazfcNb6tEZWx3M,2940
82
84
  vellum_ee/workflows/display/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
83
- vellum_ee/workflows/display/utils/vellum.py,sha256=IGHobHz0QG8TWdJNxlQ81khCmJv7piLjE64l4zc33kI,7743
84
- vellum_ee/workflows/display/vellum.py,sha256=1mcZQQ4gd5GYrVKgIQ3ejy8SqRss2CWUL0KMf44zgUc,8122
85
+ vellum_ee/workflows/display/utils/expressions.py,sha256=9FpOslDI-RCR5m4TgAu9KCHh4aTVnh7CHR2ykyMUDw0,1151
86
+ vellum_ee/workflows/display/utils/vellum.py,sha256=UjK_RxnSEmlIu9klGCPWU5RAQBmgZ7cRbRdgxaTbubE,8081
87
+ vellum_ee/workflows/display/vellum.py,sha256=PVte2gcp1_4g-8ZaM0XVAaDwf3O-kSHy7-5Q-Co-YG0,8463
85
88
  vellum_ee/workflows/display/workflows/__init__.py,sha256=kapXsC67VJcgSuiBMa86FdePG5A9kMB5Pi4Uy1O2ob4,207
86
- vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256=8inuxnxeJbysEhJIGdxLZTvQ2aPJj-OSGmSeotwe7fo,15782
89
+ vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256=Amow11LhE-GL3j8bNZ8rK1iYKjkNOhH1ECMQ-dvyLAU,17204
87
90
  vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py,sha256=kp0u8LN_2IwshLrhMImhpZx1hRyAcD5gXY-kDuuaGMQ,1269
88
91
  vellum_ee/workflows/display/workflows/tests/test_workflow_display.py,sha256=yl1ytpl9_lijOGeDPWSypWYRJ7aOEVA7NgUg81jTuCs,2229
89
- vellum_ee/workflows/display/workflows/vellum_workflow_display.py,sha256=IiHfMglir81cwPFYnwvgynp79cgzFyYVkMJAABIi3BQ,17035
92
+ vellum_ee/workflows/display/workflows/vellum_workflow_display.py,sha256=12miGvHL9_ZzXaU5r1u1TVTGSBrs8LHBVJU-DKfS0JE,18802
90
93
  vellum_ee/workflows/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
91
94
  vellum_ee/workflows/server/virtual_file_loader.py,sha256=X_DdNK7MfyOjKWekk6YQpOSCT6klKcdjT6nVJcBH1sM,1481
92
95
  vellum_ee/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -116,7 +119,7 @@ vellum/client/README.md,sha256=JkCJjmMZl4jrPj46pkmL9dpK4gSzQQmP5I7z4aME4LY,4749
116
119
  vellum/client/__init__.py,sha256=j6zi0NZ4BMC6JrwckvzMWuG5x8KoOvO4KqsLhvVCa68,117624
117
120
  vellum/client/core/__init__.py,sha256=SQ85PF84B9MuKnBwHNHWemSGuy-g_515gFYNFhvEE0I,1438
118
121
  vellum/client/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
119
- vellum/client/core/client_wrapper.py,sha256=16qoykymtSsNTtgTE4q07vaJfALO7E-GbQ6P8GVl1Mw,1868
122
+ vellum/client/core/client_wrapper.py,sha256=AN4UTP8OvOr6qMSP_VqGlHKGOVsUnQj3CLqFDhB3p5E,1868
120
123
  vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
121
124
  vellum/client/core/file.py,sha256=X9IbmkZmB2bB_DpmZAO3crWdXagOakAyn6UCOCImCPg,2322
122
125
  vellum/client/core/http_client.py,sha256=R0pQpCppnEtxccGvXl4uJ76s7ro_65Fo_erlNNLp_AI,19228
@@ -706,10 +709,10 @@ vellum/plugins/utils.py,sha256=U9ZY9KdE3RRvbcG01hXxu9CvfJD6Fo7nJDgcHjQn0FI,606
706
709
  vellum/plugins/vellum_mypy.py,sha256=QTuMSq6PiZW1dyTUZ5Bf1d4XkgFj0TKAgZLP8f4UgL4,27914
707
710
  vellum/prompts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
708
711
  vellum/prompts/blocks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
709
- vellum/prompts/blocks/compilation.py,sha256=ISuvDHaeVCPb1L7l4umORCECkDn0-rvE49hopz6c2gM,9222
712
+ vellum/prompts/blocks/compilation.py,sha256=P2gdL4bRR1j0IbvQFzS13cJzGpnaDZFhdV3x5COVvs0,9481
710
713
  vellum/prompts/blocks/exceptions.py,sha256=vmk5PV6Vyw9nKjZYQDUDW0LH8MfQNIgFvFb_mFWdIRI,50
711
714
  vellum/prompts/blocks/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
712
- vellum/prompts/blocks/tests/test_compilation.py,sha256=0DhMoc4huHR6YnNL-0aBLmWSyUfw2BpRq_gEdKsQmAc,3693
715
+ vellum/prompts/blocks/tests/test_compilation.py,sha256=WhR8L7AzxssZiizItAbbtQMXZ3An5RMUws0kfCwJBgw,4841
713
716
  vellum/prompts/blocks/types.py,sha256=6aSJQco-5kKeadfKVVXF_SrQPlIJgMYVNc-C7so1sY8,975
714
717
  vellum/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
715
718
  vellum/resources/__init__.py,sha256=sQWK7g_Z4EM7pa7fy6vy3d_DMdTJ4wVcozBn3Lx4Qpo,141
@@ -1259,7 +1262,7 @@ vellum/utils/templating/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
1259
1262
  vellum/utils/templating/constants.py,sha256=XTNmDsKa7byjw4GMZmzx2dUeYUTeMLZrPgRHcc80Kvc,613
1260
1263
  vellum/utils/templating/custom_filters.py,sha256=Q0DahYRHP4KfaUXDt9XxN-DFLBrAxlv90yaVqxScoUw,264
1261
1264
  vellum/utils/templating/exceptions.py,sha256=cDp140PP4OnInW4qAvg3KqiSiF70C71UyEAKRBR1Abo,46
1262
- vellum/utils/templating/render.py,sha256=OwdZTJlQv_qsygMX3LOFr4d1_2oz3r9vGKyj7cX05VE,1876
1265
+ vellum/utils/templating/render.py,sha256=2n6M10p2WtM2_6I10PKOIyH_gTmAo5EkxDYL2DR7F4U,2014
1263
1266
  vellum/utils/typing.py,sha256=wx_daFqD69cYkuJTVnvNrpjhqC3uuhbnyJ9_bIwC9OU,327
1264
1267
  vellum/utils/uuid.py,sha256=Ch6wWRgwICxLxJCTl5iE3EdRlZj2zADR-zUMUtjcMWM,214
1265
1268
  vellum/version.py,sha256=jq-1PlAYxN9AXuaZqbYk9ak27SgE2lw9Ia5gx1b1gVI,76
@@ -1346,7 +1349,7 @@ vellum/workflows/nodes/core/retry_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TI
1346
1349
  vellum/workflows/nodes/core/retry_node/tests/test_node.py,sha256=RM_OHwxrHwyxvlQQBJPqVBxpedFuWQ9h2-Xa3kP75sc,4399
1347
1350
  vellum/workflows/nodes/core/templating_node/__init__.py,sha256=GmyuYo81_A1_Bz6id69ozVFS6FKiuDsZTiA3I6MaL2U,70
1348
1351
  vellum/workflows/nodes/core/templating_node/node.py,sha256=zCYhq88qLTvoC9LetVrD9sLXkwHZsaWekxMhru_nV70,3752
1349
- vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py,sha256=5iZWQWdJKDHMXBY8bhpb-Dpy9FTfW1HXxGUTivykZAA,4621
1352
+ vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py,sha256=j6v3TTD4Fjq-sWcuOZOzX-okFUC18q2VKiPT9ot1bk8,5830
1350
1353
  vellum/workflows/nodes/core/try_node/__init__.py,sha256=JVD4DrldTIqFQQFrubs9KtWCCc0YCAc7Fzol5ZWIWeM,56
1351
1354
  vellum/workflows/nodes/core/try_node/node.py,sha256=bk2uhYUl10yaPJlOBWxiL7igTUrL_7mM9S2nvsdWB68,4242
1352
1355
  vellum/workflows/nodes/core/try_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -1412,7 +1415,7 @@ vellum/workflows/nodes/experimental/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQ
1412
1415
  vellum/workflows/nodes/experimental/openai_chat_completion_node/__init__.py,sha256=lsyD9laR9p7kx5-BXGH2gUTM242UhKy8SMV0SR6S2iE,90
1413
1416
  vellum/workflows/nodes/experimental/openai_chat_completion_node/node.py,sha256=1EGeiaT-Zoo6pttQFKKBcdf3dmhAbjKGaErYD5FFwlc,10185
1414
1417
  vellum/workflows/nodes/mocks.py,sha256=gvM2tyoe-V84jFbFdhQsyGAPyQBzmjn_CkhT_yxccgY,499
1415
- vellum/workflows/nodes/utils.py,sha256=T7krLipDSI007JkkH2zsfyQ-tfOBH4hyFzQ0YJKYpuw,4025
1418
+ vellum/workflows/nodes/utils.py,sha256=YRj3qIz6--N6CuDiKalsWpBmUR6z7WcRhqtLxoenDZE,4354
1416
1419
  vellum/workflows/outputs/__init__.py,sha256=AyZ4pRh_ACQIGvkf0byJO46EDnSix1ZCAXfvh-ms1QE,94
1417
1420
  vellum/workflows/outputs/base.py,sha256=RPlkKwVml6Ln8-K7kcpRl8-T-0OmB6css_UaKJdjAA8,8581
1418
1421
  vellum/workflows/ports/__init__.py,sha256=bZuMt-R7z5bKwpu4uPW7LlJeePOQWmCcDSXe5frUY5g,101
@@ -1437,7 +1440,7 @@ vellum/workflows/runner/__init__.py,sha256=i1iG5sAhtpdsrlvwgH6B-m49JsINkiWyPWs8v
1437
1440
  vellum/workflows/runner/runner.py,sha256=eY4axSyxotT_NHB3CYFA1hDSoM-eY4k3Gq5NEe7dpQw,29208
1438
1441
  vellum/workflows/sandbox.py,sha256=GVJzVjMuYzOBnSrboB0_6MMRZWBluAyQ2o7syeaeBd0,2235
1439
1442
  vellum/workflows/state/__init__.py,sha256=yUUdR-_Vl7UiixNDYQZ-GEM_kJI9dnOia75TtuNEsnE,60
1440
- vellum/workflows/state/base.py,sha256=O8BZpXTGsMVEltTs70iIms2PtZ3Qd0imf_OyoB1pKaI,14775
1443
+ vellum/workflows/state/base.py,sha256=Vkhneko3VlQrPsMLU1PYSzXU_W1u7_AraJsghiv5O-4,15512
1441
1444
  vellum/workflows/state/context.py,sha256=80b7j11AuG6engdur-AH0dUPnbwu8QyzF_-crWmvUvI,2588
1442
1445
  vellum/workflows/state/encoder.py,sha256=WdUidpOaBDx5lilJl8V8McFDHQYiCLCJR9dmktdzdZY,1836
1443
1446
  vellum/workflows/state/store.py,sha256=VYGBQgN1bpd1as5eGiouV_7scg8QsRs4_1aqZAGIsRQ,793
@@ -1468,8 +1471,8 @@ vellum/workflows/workflows/base.py,sha256=tBivLLLPtMyMi2Bd5WjbwQ2_zZFpG8rNfEidfQ
1468
1471
  vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnadGsrSZGa7t7LpJA,2008
1469
1472
  vellum/workflows/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1470
1473
  vellum/workflows/workflows/tests/test_base_workflow.py,sha256=dz5F3DuGOk9qUMjmNd-GdEE3320G5ko5nJ6J0QJyVcY,2659
1471
- vellum_ai-0.14.0.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1472
- vellum_ai-0.14.0.dist-info/METADATA,sha256=whh5Vpg1kDk2eaO-spcwQdR3inmlyl2YWrPoGWgVbYg,5407
1473
- vellum_ai-0.14.0.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1474
- vellum_ai-0.14.0.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1475
- vellum_ai-0.14.0.dist-info/RECORD,,
1474
+ vellum_ai-0.14.1.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1475
+ vellum_ai-0.14.1.dist-info/METADATA,sha256=TGCti5BkhYzjafUugASpEkqaT-cfB5-0K0zWZQPi3II,5407
1476
+ vellum_ai-0.14.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1477
+ vellum_ai-0.14.1.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1478
+ vellum_ai-0.14.1.dist-info/RECORD,,
@@ -31,6 +31,20 @@ WorkflowInputsDisplayType = TypeVar("WorkflowInputsDisplayType", bound=WorkflowI
31
31
  WorkflowInputsDisplayOverridesType = TypeVar("WorkflowInputsDisplayOverridesType", bound=WorkflowInputsDisplayOverrides)
32
32
 
33
33
 
34
+ @dataclass
35
+ class StateValueDisplayOverrides:
36
+ id: UUID
37
+
38
+
39
+ @dataclass
40
+ class StateValueDisplay(StateValueDisplayOverrides):
41
+ pass
42
+
43
+
44
+ StateValueDisplayType = TypeVar("StateValueDisplayType", bound=StateValueDisplay)
45
+ StateValueDisplayOverridesType = TypeVar("StateValueDisplayOverridesType", bound=StateValueDisplayOverrides)
46
+
47
+
34
48
  @dataclass
35
49
  class EdgeDisplayOverrides:
36
50
  id: UUID
@@ -34,6 +34,7 @@ from vellum.workflows.references import OutputReference
34
34
  from vellum.workflows.references.constant import ConstantValueReference
35
35
  from vellum.workflows.references.execution_count import ExecutionCountReference
36
36
  from vellum.workflows.references.lazy import LazyReference
37
+ from vellum.workflows.references.state_value import StateValueReference
37
38
  from vellum.workflows.references.vellum_secret import VellumSecretReference
38
39
  from vellum.workflows.references.workflow_input import WorkflowInputReference
39
40
  from vellum.workflows.types.core import JsonArray, JsonObject
@@ -44,6 +45,7 @@ from vellum.workflows.utils.uuids import uuid4_from_hash
44
45
  from vellum.workflows.utils.vellum_variables import primitive_type_to_vellum_variable_type
45
46
  from vellum_ee.workflows.display.nodes.get_node_display_class import get_node_display_class
46
47
  from vellum_ee.workflows.display.nodes.types import NodeOutputDisplay, PortDisplay, PortDisplayOverrides
48
+ from vellum_ee.workflows.display.utils.expressions import get_child_descriptor
47
49
  from vellum_ee.workflows.display.utils.vellum import convert_descriptor_to_operator, primitive_to_vellum_value
48
50
  from vellum_ee.workflows.display.vellum import CodeResourceDefinition, GenericNodeDisplayData
49
51
 
@@ -343,28 +345,8 @@ class BaseNodeDisplay(Generic[NodeType], metaclass=BaseNodeDisplayMeta):
343
345
  return self.serialize_value(display_context, value._value)
344
346
 
345
347
  if isinstance(value, LazyReference):
346
- if isinstance(value._get, str):
347
- reference_parts = value._get.split(".")
348
- if len(reference_parts) < 3:
349
- raise Exception(
350
- f"Failed to parse lazy reference: {value._get}. Only Node Output references are supported."
351
- )
352
-
353
- output_name = reference_parts[-1]
354
- nested_class_name = reference_parts[-2]
355
- if nested_class_name != "Outputs":
356
- raise Exception(
357
- f"Failed to parse lazy reference: {value._get}. Outputs are the only node reference supported."
358
- )
359
-
360
- node_class_name = ".".join(reference_parts[:-2])
361
- for node in display_context.node_displays.keys():
362
- if node.__name__ == node_class_name:
363
- return self.serialize_value(display_context, getattr(node.Outputs, output_name))
364
-
365
- raise NotImplementedError(f"Failed to find a LazyReference for: {value._get}")
366
-
367
- return self.serialize_value(display_context, value._get())
348
+ child_descriptor = get_child_descriptor(value, display_context)
349
+ return self.serialize_value(display_context, child_descriptor)
368
350
 
369
351
  if isinstance(value, WorkflowInputReference):
370
352
  workflow_input_display = display_context.global_workflow_input_displays[value]
@@ -373,6 +355,13 @@ class BaseNodeDisplay(Generic[NodeType], metaclass=BaseNodeDisplayMeta):
373
355
  "input_variable_id": str(workflow_input_display.id),
374
356
  }
375
357
 
358
+ if isinstance(value, StateValueReference):
359
+ state_value_display = display_context.global_state_value_displays[value]
360
+ return {
361
+ "type": "STATE_VALUE",
362
+ "state_variable_id": str(state_value_display.id),
363
+ }
364
+
376
365
  if isinstance(value, OutputReference):
377
366
  upstream_node, output_display = display_context.global_node_output_displays[value]
378
367
  upstream_node_display = display_context.global_node_displays[upstream_node]
@@ -0,0 +1,52 @@
1
+ from vellum.workflows import BaseWorkflow
2
+ from vellum.workflows.nodes import BaseNode
3
+ from vellum.workflows.nodes.displayable.inline_prompt_node.node import InlinePromptNode
4
+ from vellum.workflows.references.lazy import LazyReference
5
+ from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
6
+ from vellum_ee.workflows.display.workflows.vellum_workflow_display import VellumWorkflowDisplay
7
+
8
+
9
+ def test_serialize_node__lazy_reference_in_prompt_inputs():
10
+ # GIVEN a prompt node with a lazy reference in the prompt inputs
11
+ class LazyReferencePromptNode(InlinePromptNode):
12
+ prompt_inputs = {"attr": LazyReference[str]("OtherNode.Outputs.result")}
13
+ blocks = []
14
+ ml_model = "gpt-4o"
15
+
16
+ class OtherNode(BaseNode):
17
+ class Outputs:
18
+ result: str
19
+
20
+ # AND a workflow with both nodes
21
+ class Workflow(BaseWorkflow):
22
+ graph = LazyReferencePromptNode >> OtherNode
23
+
24
+ # WHEN the workflow is serialized
25
+ workflow_display = get_workflow_display(base_display_class=VellumWorkflowDisplay, workflow_class=Workflow)
26
+ serialized_workflow: dict = workflow_display.serialize()
27
+
28
+ # THEN the node should properly serialize the attribute reference
29
+ lazy_reference_node = next(
30
+ node
31
+ for node in serialized_workflow["workflow_raw_data"]["nodes"]
32
+ if node["id"] == str(LazyReferencePromptNode.__id__)
33
+ )
34
+
35
+ assert lazy_reference_node["inputs"] == [
36
+ {
37
+ "id": "fba6a4d5-835a-4e99-afb7-f6a4aed15110",
38
+ "key": "attr",
39
+ "value": {
40
+ "combinator": "OR",
41
+ "rules": [
42
+ {
43
+ "type": "NODE_OUTPUT",
44
+ "data": {
45
+ "node_id": str(OtherNode.__id__),
46
+ "output_id": "7f377cb8-4eca-4f1c-9239-9925f9495d84",
47
+ },
48
+ }
49
+ ],
50
+ },
51
+ }
52
+ ]
@@ -25,6 +25,7 @@ def test_vellum_workflow_display__serialize_empty_workflow():
25
25
  # THEN it should return the expected config
26
26
  assert exec_config == {
27
27
  "input_variables": [],
28
+ "state_variables": [],
28
29
  "output_variables": [],
29
30
  "workflow_raw_data": {
30
31
  "definition": {
@@ -4,10 +4,11 @@ from typing import Any, Dict, Tuple, Type
4
4
 
5
5
  from vellum.workflows.nodes.bases.base import BaseNode
6
6
  from vellum.workflows.references.output import OutputReference
7
+ from vellum.workflows.references.state_value import StateValueReference
7
8
  from vellum.workflows.references.workflow_input import WorkflowInputReference
8
9
  from vellum.workflows.types.core import JsonObject
9
10
  from vellum.workflows.types.generics import NodeType
10
- from vellum_ee.workflows.display.base import WorkflowInputsDisplayType
11
+ from vellum_ee.workflows.display.base import StateValueDisplayType, WorkflowInputsDisplayType
11
12
  from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
12
13
  from vellum_ee.workflows.display.nodes.get_node_display_class import get_node_display_class
13
14
  from vellum_ee.workflows.display.nodes.types import NodeOutputDisplay
@@ -22,6 +23,7 @@ def serialize_node():
22
23
  node_class: Type[NodeType],
23
24
  base_class: type[BaseNodeDisplay[Any]] = BaseNodeDisplay,
24
25
  global_workflow_input_displays: Dict[WorkflowInputReference, WorkflowInputsDisplayType] = {},
26
+ global_state_value_displays: Dict[StateValueReference, StateValueDisplayType] = {},
25
27
  global_node_displays: Dict[Type[BaseNode], NodeDisplayType] = {},
26
28
  global_node_output_displays: Dict[OutputReference, Tuple[Type[BaseNode], NodeOutputDisplay]] = {},
27
29
  ) -> JsonObject:
@@ -37,6 +39,7 @@ def serialize_node():
37
39
  ),
38
40
  node_displays={node_class: node_display},
39
41
  global_workflow_input_displays=global_workflow_input_displays,
42
+ global_state_value_displays=global_state_value_displays,
40
43
  global_node_displays=global_node_displays,
41
44
  global_node_output_displays=global_node_output_displays,
42
45
  )