vellum-ai 0.12.1__py3-none-any.whl → 0.12.3__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.
@@ -1,10 +1,11 @@
1
1
  # This file was auto-generated by Fern from our API Definition.
2
2
 
3
- from ..environment import VellumEnvironment
4
3
  import typing
4
+
5
5
  import httpx
6
- from .http_client import HttpClient
7
- from .http_client import AsyncHttpClient
6
+
7
+ from ..environment import VellumEnvironment
8
+ from .http_client import AsyncHttpClient, HttpClient
8
9
 
9
10
 
10
11
  class BaseClientWrapper:
@@ -17,7 +18,7 @@ class BaseClientWrapper:
17
18
  headers: typing.Dict[str, str] = {
18
19
  "X-Fern-Language": "Python",
19
20
  "X-Fern-SDK-Name": "vellum-ai",
20
- "X-Fern-SDK-Version": "0.12.1",
21
+ "X-Fern-SDK-Version": "0.12.3",
21
22
  }
22
23
  headers["X_API_KEY"] = self.api_key
23
24
  return headers
@@ -13,7 +13,7 @@ class PromptRequestJsonInput(UniversalBaseModel):
13
13
  """
14
14
 
15
15
  type: typing.Literal["JSON"] = "JSON"
16
- value: typing.Dict[str, typing.Optional[typing.Any]]
16
+ value: typing.Optional[typing.Any] = None
17
17
 
18
18
  if IS_PYDANTIC_V2:
19
19
  model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
@@ -17,7 +17,9 @@ if TYPE_CHECKING:
17
17
  from vellum.workflows.expressions.greater_than_or_equal_to import GreaterThanOrEqualToExpression
18
18
  from vellum.workflows.expressions.in_ import InExpression
19
19
  from vellum.workflows.expressions.is_blank import IsBlankExpression
20
+ from vellum.workflows.expressions.is_nil import IsNilExpression
20
21
  from vellum.workflows.expressions.is_not_blank import IsNotBlankExpression
22
+ from vellum.workflows.expressions.is_not_nil import IsNotNilExpression
21
23
  from vellum.workflows.expressions.is_not_null import IsNotNullExpression
22
24
  from vellum.workflows.expressions.is_not_undefined import IsNotUndefinedExpression
23
25
  from vellum.workflows.expressions.is_null import IsNullExpression
@@ -268,6 +270,16 @@ class BaseDescriptor(Generic[_T]):
268
270
 
269
271
  return IsNotNullExpression(expression=self)
270
272
 
273
+ def is_nil(self) -> "IsNilExpression":
274
+ from vellum.workflows.expressions.is_nil import IsNilExpression
275
+
276
+ return IsNilExpression(expression=self)
277
+
278
+ def is_not_nil(self) -> "IsNotNilExpression":
279
+ from vellum.workflows.expressions.is_not_nil import IsNotNilExpression
280
+
281
+ return IsNotNilExpression(expression=self)
282
+
271
283
  def is_undefined(self) -> "IsUndefinedExpression":
272
284
  from vellum.workflows.expressions.is_undefined import IsUndefinedExpression
273
285
 
@@ -1,6 +1,7 @@
1
1
  import pytest
2
2
 
3
3
  from vellum.workflows.descriptors.utils import resolve_value
4
+ from vellum.workflows.nodes.bases.base import BaseNode
4
5
  from vellum.workflows.state.base import BaseState
5
6
 
6
7
 
@@ -16,6 +17,13 @@ class FixtureState(BaseState):
16
17
  "foo": "bar",
17
18
  }
18
19
 
20
+ eta = None
21
+
22
+
23
+ class DummyNode(BaseNode[FixtureState]):
24
+ class Outputs(BaseNode.Outputs):
25
+ empty: str
26
+
19
27
 
20
28
  @pytest.mark.parametrize(
21
29
  ["descriptor", "expected_value"],
@@ -36,7 +44,23 @@ class FixtureState(BaseState):
36
44
  (FixtureState.gamma.does_not_begin_with(FixtureState.delta), True),
37
45
  (FixtureState.gamma.does_not_end_with(FixtureState.delta), True),
38
46
  (FixtureState.alpha.is_null(), False),
47
+ (FixtureState.eta.is_null(), True),
48
+ (DummyNode.Outputs.empty.is_null(), False),
39
49
  (FixtureState.alpha.is_not_null(), True),
50
+ (FixtureState.eta.is_not_null(), False),
51
+ (DummyNode.Outputs.empty.is_not_null(), True),
52
+ (FixtureState.alpha.is_nil(), False),
53
+ (FixtureState.eta.is_nil(), True),
54
+ (DummyNode.Outputs.empty.is_nil(), True),
55
+ (FixtureState.alpha.is_not_nil(), True),
56
+ (FixtureState.eta.is_not_nil(), False),
57
+ (DummyNode.Outputs.empty.is_not_nil(), False),
58
+ (FixtureState.alpha.is_undefined(), False),
59
+ (FixtureState.eta.is_undefined(), False),
60
+ (DummyNode.Outputs.empty.is_undefined(), True),
61
+ (FixtureState.alpha.is_not_undefined(), True),
62
+ (FixtureState.eta.is_not_undefined(), True),
63
+ (DummyNode.Outputs.empty.is_not_undefined(), False),
40
64
  (FixtureState.delta.in_(FixtureState.gamma), True),
41
65
  (FixtureState.delta.not_in(FixtureState.gamma), False),
42
66
  (FixtureState.alpha.between(FixtureState.beta, FixtureState.epsilon), False),
@@ -66,8 +90,24 @@ class FixtureState(BaseState):
66
90
  "does_not_contain",
67
91
  "does_not_begin_with",
68
92
  "does_not_end_with",
69
- "is_null",
70
- "is_not_null",
93
+ "is_null_on_value",
94
+ "is_null_on_null",
95
+ "is_null_on_undefined",
96
+ "is_not_null_on_value",
97
+ "is_not_null_on_null",
98
+ "is_not_null_on_undefined",
99
+ "is_nil_on_value",
100
+ "is_nil_on_null",
101
+ "is_nil_on_undefined",
102
+ "is_not_nil_on_value",
103
+ "is_not_nil_on_null",
104
+ "is_not_nil_on_undefined",
105
+ "is_undefined_on_value",
106
+ "is_undefined_on_null",
107
+ "is_undefined_on_undefined",
108
+ "is_not_undefined_on_value",
109
+ "is_not_undefined_on_null",
110
+ "is_not_undefined_on_undefined",
71
111
  "in_",
72
112
  "not_in",
73
113
  "between",
@@ -10,7 +10,7 @@ from vellum.workflows.ports.port import Port
10
10
  from vellum.workflows.references.node import NodeReference
11
11
  from vellum.workflows.types.generics import OutputsType
12
12
 
13
- from .types import BaseEvent, default_serializer, serialize_type_encoder
13
+ from .types import BaseEvent, default_serializer, serialize_type_encoder_with_id
14
14
 
15
15
  if TYPE_CHECKING:
16
16
  from vellum.workflows.nodes.bases import BaseNode
@@ -21,7 +21,7 @@ class _BaseNodeExecutionBody(UniversalBaseModel):
21
21
 
22
22
  @field_serializer("node_definition")
23
23
  def serialize_node_definition(self, node_definition: Type, _info: Any) -> Dict[str, Any]:
24
- return serialize_type_encoder(node_definition)
24
+ return serialize_type_encoder_with_id(node_definition)
25
25
 
26
26
  # Couldn't get this to work with model_config.exclude_none or model_config.exclude_defaults
27
27
  # so we're excluding null invoked_ports manually here for now
@@ -28,6 +28,7 @@ from vellum.workflows.inputs.base import BaseInputs
28
28
  from vellum.workflows.nodes.bases.base import BaseNode
29
29
  from vellum.workflows.outputs.base import BaseOutput
30
30
  from vellum.workflows.state.base import BaseState
31
+ from vellum.workflows.utils.uuids import uuid4_from_hash
31
32
  from vellum.workflows.workflows.base import BaseWorkflow
32
33
 
33
34
 
@@ -48,6 +49,8 @@ class MockWorkflow(BaseWorkflow[MockInputs, BaseState]):
48
49
 
49
50
  name_parts = __name__.split(".")
50
51
  module_root = name_parts[: name_parts.index("events")]
52
+ mock_workflow_uuid = str(uuid4_from_hash(MockWorkflow.__qualname__))
53
+ mock_node_uuid = str(uuid4_from_hash(MockNode.__qualname__))
51
54
 
52
55
 
53
56
  @pytest.mark.parametrize(
@@ -73,6 +76,7 @@ module_root = name_parts[: name_parts.index("events")]
73
76
  "name": "workflow.execution.initiated",
74
77
  "body": {
75
78
  "workflow_definition": {
79
+ "id": mock_workflow_uuid,
76
80
  "name": "MockWorkflow",
77
81
  "module": module_root + ["events", "tests", "test_event"],
78
82
  },
@@ -113,6 +117,7 @@ module_root = name_parts[: name_parts.index("events")]
113
117
  "name": "node.execution.initiated",
114
118
  "body": {
115
119
  "node_definition": {
120
+ "id": mock_node_uuid,
116
121
  "name": "MockNode",
117
122
  "module": module_root + ["events", "tests", "test_event"],
118
123
  },
@@ -122,11 +127,13 @@ module_root = name_parts[: name_parts.index("events")]
122
127
  },
123
128
  "parent": {
124
129
  "node_definition": {
130
+ "id": mock_node_uuid,
125
131
  "name": "MockNode",
126
132
  "module": module_root + ["events", "tests", "test_event"],
127
133
  },
128
134
  "parent": {
129
135
  "workflow_definition": {
136
+ "id": mock_workflow_uuid,
130
137
  "name": "MockWorkflow",
131
138
  "module": module_root + ["events", "tests", "test_event"],
132
139
  },
@@ -162,6 +169,7 @@ module_root = name_parts[: name_parts.index("events")]
162
169
  "name": "workflow.execution.streaming",
163
170
  "body": {
164
171
  "workflow_definition": {
172
+ "id": mock_workflow_uuid,
165
173
  "name": "MockWorkflow",
166
174
  "module": module_root + ["events", "tests", "test_event"],
167
175
  },
@@ -195,6 +203,7 @@ module_root = name_parts[: name_parts.index("events")]
195
203
  "name": "workflow.execution.fulfilled",
196
204
  "body": {
197
205
  "workflow_definition": {
206
+ "id": mock_workflow_uuid,
198
207
  "name": "MockWorkflow",
199
208
  "module": module_root + ["events", "tests", "test_event"],
200
209
  },
@@ -228,6 +237,7 @@ module_root = name_parts[: name_parts.index("events")]
228
237
  "name": "workflow.execution.rejected",
229
238
  "body": {
230
239
  "workflow_definition": {
240
+ "id": mock_workflow_uuid,
231
241
  "name": "MockWorkflow",
232
242
  "module": module_root + ["events", "tests", "test_event"],
233
243
  },
@@ -262,6 +272,7 @@ module_root = name_parts[: name_parts.index("events")]
262
272
  "name": "node.execution.streaming",
263
273
  "body": {
264
274
  "node_definition": {
275
+ "id": mock_node_uuid,
265
276
  "name": "MockNode",
266
277
  "module": module_root + ["events", "tests", "test_event"],
267
278
  },
@@ -296,6 +307,7 @@ module_root = name_parts[: name_parts.index("events")]
296
307
  "name": "node.execution.fulfilled",
297
308
  "body": {
298
309
  "node_definition": {
310
+ "id": mock_node_uuid,
299
311
  "name": "MockNode",
300
312
  "module": module_root + ["events", "tests", "test_event"],
301
313
  },
@@ -28,6 +28,15 @@ def serialize_type_encoder(obj: type) -> Dict[str, Any]:
28
28
  }
29
29
 
30
30
 
31
+ def serialize_type_encoder_with_id(obj: type) -> Dict[str, Any]:
32
+ if not hasattr(obj, "__id__"):
33
+ raise AttributeError(f"The object of type '{type(obj).__name__}' must have an '__id__' attribute.")
34
+ return {
35
+ "id": getattr(obj, "__id__"),
36
+ **serialize_type_encoder(obj),
37
+ }
38
+
39
+
31
40
  def default_serializer(obj: Any) -> Any:
32
41
  return json.loads(
33
42
  json.dumps(
@@ -38,17 +47,18 @@ def default_serializer(obj: Any) -> Any:
38
47
 
39
48
 
40
49
  class CodeResourceDefinition(UniversalBaseModel):
50
+ id: UUID
41
51
  name: str
42
52
  module: List[str]
43
53
 
44
54
  @staticmethod
45
55
  def encode(obj: type) -> "CodeResourceDefinition":
46
- return CodeResourceDefinition(**serialize_type_encoder(obj))
56
+ return CodeResourceDefinition(**serialize_type_encoder_with_id(obj))
47
57
 
48
58
 
49
59
  VellumCodeResourceDefinition = Annotated[
50
60
  CodeResourceDefinition,
51
- BeforeValidator(lambda d: (d if type(d) is dict else serialize_type_encoder(d))),
61
+ BeforeValidator(lambda d: (d if type(d) is dict else serialize_type_encoder_with_id(d))),
52
62
  ]
53
63
 
54
64
 
@@ -16,7 +16,7 @@ from .node import (
16
16
  NodeExecutionResumedEvent,
17
17
  NodeExecutionStreamingEvent,
18
18
  )
19
- from .types import BaseEvent, default_serializer, serialize_type_encoder
19
+ from .types import BaseEvent, default_serializer, serialize_type_encoder_with_id
20
20
 
21
21
  if TYPE_CHECKING:
22
22
  from vellum.workflows.workflows.base import BaseWorkflow
@@ -27,7 +27,7 @@ class _BaseWorkflowExecutionBody(UniversalBaseModel):
27
27
 
28
28
  @field_serializer("workflow_definition")
29
29
  def serialize_workflow_definition(self, workflow_definition: Type, _info: Any) -> Dict[str, Any]:
30
- return serialize_type_encoder(workflow_definition)
30
+ return serialize_type_encoder_with_id(workflow_definition)
31
31
 
32
32
 
33
33
  class _BaseWorkflowEvent(BaseEvent):
@@ -0,0 +1,22 @@
1
+ from typing import Generic, TypeVar, Union
2
+
3
+ from vellum.workflows.constants import UNDEF
4
+ from vellum.workflows.descriptors.base import BaseDescriptor
5
+ from vellum.workflows.descriptors.utils import resolve_value
6
+ from vellum.workflows.state.base import BaseState
7
+
8
+ _T = TypeVar("_T")
9
+
10
+
11
+ class IsNilExpression(BaseDescriptor[bool], Generic[_T]):
12
+ def __init__(
13
+ self,
14
+ *,
15
+ expression: Union[BaseDescriptor[_T], _T],
16
+ ) -> None:
17
+ super().__init__(name=f"{expression} is null or undefined", types=(bool,))
18
+ self._expression = expression
19
+
20
+ def resolve(self, state: "BaseState") -> bool:
21
+ expression = resolve_value(self._expression, state)
22
+ return expression is None or expression is UNDEF
@@ -0,0 +1,22 @@
1
+ from typing import Generic, TypeVar, Union
2
+
3
+ from vellum.workflows.constants import UNDEF
4
+ from vellum.workflows.descriptors.base import BaseDescriptor
5
+ from vellum.workflows.descriptors.utils import resolve_value
6
+ from vellum.workflows.state.base import BaseState
7
+
8
+ _T = TypeVar("_T")
9
+
10
+
11
+ class IsNotNilExpression(BaseDescriptor[bool], Generic[_T]):
12
+ def __init__(
13
+ self,
14
+ *,
15
+ expression: Union[BaseDescriptor[_T], _T],
16
+ ) -> None:
17
+ super().__init__(name=f"{expression} is not null and not undefined", types=(bool,))
18
+ self._expression = expression
19
+
20
+ def resolve(self, state: "BaseState") -> bool:
21
+ expression = resolve_value(self._expression, state)
22
+ return expression is not None and expression is not UNDEF
@@ -13,7 +13,7 @@ class IsNotNullExpression(BaseDescriptor[bool], Generic[_T]):
13
13
  *,
14
14
  expression: Union[BaseDescriptor[_T], _T],
15
15
  ) -> None:
16
- super().__init__(name=f"{expression} is not None", types=(bool,))
16
+ super().__init__(name=f"{expression} is not null", types=(bool,))
17
17
  self._expression = expression
18
18
 
19
19
  def resolve(self, state: "BaseState") -> bool:
@@ -13,7 +13,7 @@ class IsNullExpression(BaseDescriptor[bool], Generic[_T]):
13
13
  *,
14
14
  expression: Union[BaseDescriptor[_T], _T],
15
15
  ) -> None:
16
- super().__init__(name=f"{expression} is None", types=(bool,))
16
+ super().__init__(name=f"{expression} is null", types=(bool,))
17
17
  self._expression = expression
18
18
 
19
19
  def resolve(self, state: "BaseState") -> bool:
@@ -2,11 +2,30 @@ from functools import cache
2
2
  from typing import Type
3
3
 
4
4
  from vellum.workflows.nodes import BaseNode
5
+ from vellum.workflows.ports.port import Port
5
6
  from vellum.workflows.types.generics import NodeType
6
7
 
7
8
  ADORNMENT_MODULE_NAME = "<adornment>"
8
9
 
9
10
 
11
+ @cache
12
+ def get_unadorned_node(node: Type[BaseNode]) -> Type[BaseNode]:
13
+ wrapped_node = getattr(node, "__wrapped_node__", None)
14
+ if wrapped_node is not None:
15
+ return get_unadorned_node(wrapped_node)
16
+
17
+ return node
18
+
19
+
20
+ @cache
21
+ def get_unadorned_port(port: Port) -> Port:
22
+ unadorned_node = get_unadorned_node(port.node_class)
23
+ if unadorned_node == port.node_class:
24
+ return port
25
+
26
+ return getattr(unadorned_node.Ports, port.name)
27
+
28
+
10
29
  @cache
11
30
  def get_wrapped_node(node: Type[NodeType]) -> Type[BaseNode]:
12
31
  wrapped_node = getattr(node, "__wrapped_node__", None)
@@ -4,6 +4,7 @@ import importlib
4
4
  import inspect
5
5
 
6
6
  from vellum.plugins.utils import load_runtime_plugins
7
+ from vellum.workflows.utils.uuids import uuid4_from_hash
7
8
  from vellum.workflows.workflows.event_filters import workflow_event_filter
8
9
 
9
10
  load_runtime_plugins()
@@ -11,7 +12,7 @@ load_runtime_plugins()
11
12
  from datetime import datetime
12
13
  from functools import lru_cache
13
14
  from threading import Event as ThreadingEvent
14
- from uuid import uuid4
15
+ from uuid import UUID, uuid4
15
16
  from typing import (
16
17
  Any,
17
18
  Callable,
@@ -85,13 +86,17 @@ class _BaseWorkflowMeta(type):
85
86
  if "graph" not in dct:
86
87
  dct["graph"] = set()
87
88
 
88
- return super().__new__(mcs, name, bases, dct)
89
+ cls = super().__new__(mcs, name, bases, dct)
90
+ workflow_class = cast(Type["BaseWorkflow"], cls)
91
+ workflow_class.__id__ = uuid4_from_hash(workflow_class.__qualname__)
92
+ return workflow_class
89
93
 
90
94
 
91
95
  GraphAttribute = Union[Type[BaseNode], Graph, Set[Type[BaseNode]], Set[Graph]]
92
96
 
93
97
 
94
98
  class BaseWorkflow(Generic[WorkflowInputsType, StateType], metaclass=_BaseWorkflowMeta):
99
+ __id__: UUID = uuid4_from_hash(__qualname__)
95
100
  graph: ClassVar[GraphAttribute]
96
101
  emitters: List[BaseWorkflowEmitter]
97
102
  resolvers: List[BaseWorkflowResolver]
@@ -1,6 +1,6 @@
1
1
  from typing import TYPE_CHECKING, Type
2
2
 
3
- from vellum.workflows.events.types import CodeResourceDefinition
3
+ from vellum.workflows.events.types import VellumCodeResourceDefinition
4
4
 
5
5
  if TYPE_CHECKING:
6
6
  from vellum.workflows.events.workflow import WorkflowEvent
@@ -47,7 +47,7 @@ def root_workflow_event_filter(workflow_definition: Type["BaseWorkflow"], event:
47
47
  return False
48
48
 
49
49
  event_parent_definition = event.parent.workflow_definition
50
- current_workflow_definition = CodeResourceDefinition.encode(workflow_definition)
50
+ current_workflow_definition = VellumCodeResourceDefinition.encode(workflow_definition)
51
51
 
52
52
  return event_parent_definition.model_dump() == current_workflow_definition.model_dump()
53
53
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vellum-ai
3
- Version: 0.12.1
3
+ Version: 0.12.3
4
4
  Summary:
5
5
  License: MIT
6
6
  Requires-Python: >=3.9,<4.0
@@ -20,7 +20,7 @@ vellum_ee/workflows/display/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
20
20
  vellum_ee/workflows/display/base.py,sha256=3ZFUYRNKL24fBqXhKpa_Dq2W1a-a86J20dmJYA3H2eY,1755
21
21
  vellum_ee/workflows/display/nodes/__init__.py,sha256=5XOcZJXYUgaLS55QgRJzyQ_W1tpeprjnYAeYVezqoGw,160
22
22
  vellum_ee/workflows/display/nodes/base_node_display.py,sha256=23PLqcpMe_mYkYdug9PDb6Br7o64Thx9-IhcviKGvGo,6662
23
- vellum_ee/workflows/display/nodes/base_node_vellum_display.py,sha256=E7BFiDv7RdPt_CYhmlgc5ZoQo4JcSQKBGFsAQg0OaJ4,2113
23
+ vellum_ee/workflows/display/nodes/base_node_vellum_display.py,sha256=7F4zQnZQBOTp9turUUS41RaO40Z14m851WOLJHgmHPU,2234
24
24
  vellum_ee/workflows/display/nodes/get_node_display_class.py,sha256=vyKeJAevAXvEAEtWeTEdBZXD3eJQYW_DEXLKVZ5KmYc,1325
25
25
  vellum_ee/workflows/display/nodes/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
26
  vellum_ee/workflows/display/nodes/tests/test_base_node_display.py,sha256=QqR3Ly0RNrXwOeLdW5nERDFt0gRPf76n1bPES6o5UN4,1093
@@ -29,11 +29,11 @@ vellum_ee/workflows/display/nodes/utils.py,sha256=sloya5TpXsnot1HURc9L51INwflRqU
29
29
  vellum_ee/workflows/display/nodes/vellum/__init__.py,sha256=nmPLj8vkbVCS46XQqmHq8Xj8Mr36wCK_vWf26A9KIkw,1505
30
30
  vellum_ee/workflows/display/nodes/vellum/api_node.py,sha256=4SSQGecKWHuoGy5YIGJeOZVHGKwTs_8Y-gf3GvsHb0M,8506
31
31
  vellum_ee/workflows/display/nodes/vellum/code_execution_node.py,sha256=_sdLmmOa1ZqZQZXzw0GMoUpgnV1sdOfc_19LJCBS_Xc,4288
32
- vellum_ee/workflows/display/nodes/vellum/conditional_node.py,sha256=9JjtXTpyC14X5e1ntue2BcDif-jJA-wyDBd3hE6_gv4,13282
32
+ vellum_ee/workflows/display/nodes/vellum/conditional_node.py,sha256=TP7ItMeEXbVbkGr5Qwjv8vl9V0Fi9QBE04d3kdJH4JE,13666
33
33
  vellum_ee/workflows/display/nodes/vellum/error_node.py,sha256=ygTjSjYDI4DtkxADWub5rhBnRWItMKWF6fezBrgpOKA,1979
34
34
  vellum_ee/workflows/display/nodes/vellum/final_output_node.py,sha256=t5iJQVoRT5g-v2IiUb4kFYdvUVKch0zn27016pzDZoo,2761
35
35
  vellum_ee/workflows/display/nodes/vellum/guardrail_node.py,sha256=3TJvHX_Uuf_gr94VkYc_zmNH8I5p71ChIeoAbJZ3ddY,2158
36
- vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py,sha256=aU_jZeV0CC3JkIo_LHSh7peLbJEqEaV4odrLPtqzRxI,7375
36
+ vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py,sha256=E7U4B05-KSlPvTp0nYQTtGPkNa5563VxrNBQmKwvTqw,7267
37
37
  vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py,sha256=x5wiuWbRjxNcPGu8BoBEKHwPeqCpHE-vrGjAdM5TJOs,4721
38
38
  vellum_ee/workflows/display/nodes/vellum/map_node.py,sha256=AqUlItgSZij12qRKguKVmDbbaLuDy3Cdom5uOlJPqrc,3640
39
39
  vellum_ee/workflows/display/nodes/vellum/merge_node.py,sha256=jzO63B9KiEAncnBqmz2ZTcxjmEHozMEe7WnfpcpsQYg,3195
@@ -44,7 +44,7 @@ vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py,sha256=z
44
44
  vellum_ee/workflows/display/nodes/vellum/templating_node.py,sha256=UNYxoE-89agE8ugK0aWg_uN61jPqlC2VSxWHk568sN4,3324
45
45
  vellum_ee/workflows/display/nodes/vellum/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
46
  vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py,sha256=aJfQnIvlrRHVKgQid_gg6VQKkJyPgFnzbvWt9_t0Vz0,3860
47
- vellum_ee/workflows/display/nodes/vellum/try_node.py,sha256=4k9DdjjCkZ_-4qynwg40IipT5Sq2WwgYFFE8WMnMdr0,2612
47
+ vellum_ee/workflows/display/nodes/vellum/try_node.py,sha256=hB8dcGMGkuC95kk9hmZUgHsCLwEA37fHTFXj0JzbRjM,4692
48
48
  vellum_ee/workflows/display/nodes/vellum/utils.py,sha256=3QsKS5Kht2Nod4A18T0bb4filK9AkyK5oImVlViK3l8,4643
49
49
  vellum_ee/workflows/display/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
50
50
  vellum_ee/workflows/display/tests/test_vellum_workflow_display.py,sha256=TEg3QbdE7rLbEhml9pMWmay--phsekGlfGVhTblxCGE,1727
@@ -70,13 +70,13 @@ vellum_ee/workflows/display/vellum.py,sha256=OSv0ZS50h1zJbunJ9TH7VEWFw-exXdK_Zsd
70
70
  vellum_ee/workflows/display/workflows/__init__.py,sha256=kapXsC67VJcgSuiBMa86FdePG5A9kMB5Pi4Uy1O2ob4,207
71
71
  vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256=ydAbFMzcY2LURINZbXYm9BAXZdIa3-7rQ86Kupo7qcA,12804
72
72
  vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py,sha256=AMxNnTm2z3LIR5rqxoCAfuy37F2FTuSRDVtKUoezO8M,1184
73
- vellum_ee/workflows/display/workflows/vellum_workflow_display.py,sha256=CvxUFudijGW4M7vapm_qrNG4X36PZxzFh6n6qBE9E1Y,17134
73
+ vellum_ee/workflows/display/workflows/vellum_workflow_display.py,sha256=GhIviEMDWNw1p8z20ta08T5PeNCVJs5p2hrOX1uyNxg,17066
74
74
  vellum/__init__.py,sha256=QmGeEPXeFxgkZa849KKK3wH3Y641wyt00Rytfay6KiM,35520
75
75
  vellum/client/README.md,sha256=JkCJjmMZl4jrPj46pkmL9dpK4gSzQQmP5I7z4aME4LY,4749
76
76
  vellum/client/__init__.py,sha256=o4m7iRZWEV8rP3GkdaztHAjNmjxjWERlarviFoHzuKI,110927
77
77
  vellum/client/core/__init__.py,sha256=SQ85PF84B9MuKnBwHNHWemSGuy-g_515gFYNFhvEE0I,1438
78
78
  vellum/client/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
79
- vellum/client/core/client_wrapper.py,sha256=H2IXjD1b02FWzrMw028nrenbKt081feJ95KpLGbDnFk,1890
79
+ vellum/client/core/client_wrapper.py,sha256=V6KKyJKYfRUGFN1-YsTg1jmCrvWiVWYEgcetm7xdB2U,1868
80
80
  vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
81
81
  vellum/client/core/file.py,sha256=X9IbmkZmB2bB_DpmZAO3crWdXagOakAyn6UCOCImCPg,2322
82
82
  vellum/client/core/http_client.py,sha256=R0pQpCppnEtxccGvXl4uJ76s7ro_65Fo_erlNNLp_AI,19228
@@ -407,7 +407,7 @@ vellum/client/types/prompt_output.py,sha256=NpDGJNIYIivzQJnBeoJLpJlCk7gqBESLwv5Q
407
407
  vellum/client/types/prompt_parameters.py,sha256=Vkwh4zI9gX1DuGQxrWiUUa1TshTfnPlS7_yRrziD5qg,1046
408
408
  vellum/client/types/prompt_request_chat_history_input.py,sha256=DB2io5piMSyA89f5lnIVYO4MLZoNALNSufx8Y-oOwOE,790
409
409
  vellum/client/types/prompt_request_input.py,sha256=brEdYhYm74Ac8XjK9wF0rKOLgnqd_Cg19yMS7VfB4qQ,400
410
- vellum/client/types/prompt_request_json_input.py,sha256=6qLOPsNtDTIz43qJdZSgLwO9SWLe_plSJDH11xWGS6A,750
410
+ vellum/client/types/prompt_request_json_input.py,sha256=vLhwvCWL_yjVfDzT4921xK4Ql92OkvG-ruvOC_uppFI,739
411
411
  vellum/client/types/prompt_request_string_input.py,sha256=8GSFhtN3HeYssbDRY7B5SCh5Qrp67340D9c3oINpCmw,714
412
412
  vellum/client/types/prompt_settings.py,sha256=lSQeNofj9EzOncr81hGRE2ZBhgRCqDYMT5e3a66PuqA,586
413
413
  vellum/client/types/raw_prompt_execution_overrides_request.py,sha256=x4Chkm_NxXySOEyA6s6J_mhhiM91KCcQbu6pQETB8RI,927
@@ -1203,8 +1203,8 @@ vellum/workflows/__init__.py,sha256=CssPsbNvN6rDhoLuqpEv7MMKGa51vE6dvAh6U31Pcio,
1203
1203
  vellum/workflows/constants.py,sha256=Z0W4YlqfSlSgWC11PrVUPs6ZOBeIaQ78E_90J1hohiw,789
1204
1204
  vellum/workflows/context.py,sha256=R8qdsFbD_0p7B6PWnyvSrZ_aOgMtGw-_uk0P0UAmwLA,1230
1205
1205
  vellum/workflows/descriptors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1206
- vellum/workflows/descriptors/base.py,sha256=yLfr5qW5o7B2tLVvxEGeh-f6qiAQ735-9xrKOZ3HMc4,13830
1207
- vellum/workflows/descriptors/tests/test_utils.py,sha256=Ct8ZRdK3TghVzuqv3a4pWk6p04szt5KOaizzk9LhY5Y,2849
1206
+ vellum/workflows/descriptors/base.py,sha256=BhYd5O9_3fjS_Vet9Q2_kyUJCySHGVM_HWaOBtctkNA,14320
1207
+ vellum/workflows/descriptors/tests/test_utils.py,sha256=bjWNlmyCmtpDZmIzwYmS1Yh7kulmMO6LgNJFYVFCg4o,4377
1208
1208
  vellum/workflows/descriptors/utils.py,sha256=lO_dbr5g3PXpHPtVBkdguAK4-1qayZ7RXjl3BgAhrMM,3795
1209
1209
  vellum/workflows/edges/__init__.py,sha256=wSkmAnz9xyi4vZwtDbKxwlplt2skD7n3NsxkvR_pUus,50
1210
1210
  vellum/workflows/edges/edge.py,sha256=N0SnY3gKVuxImPAdCbPMPlHJIXbkQ3fwq_LbJRvVMFc,677
@@ -1215,11 +1215,11 @@ vellum/workflows/environment/environment.py,sha256=IwcVSwA51jW1JTN_MAN22UbeAtZhi
1215
1215
  vellum/workflows/errors/__init__.py,sha256=tWGPu5xyAU8gRb8_bl0fL7OfU3wxQ9UH6qVwy4X4P_Q,113
1216
1216
  vellum/workflows/errors/types.py,sha256=mvywC2sXtpRrkDRfTx-O6aXAp0hOFyx27a1tqguKt4g,2493
1217
1217
  vellum/workflows/events/__init__.py,sha256=6pxxceJo2dcaRkWtkDAYlUQZ-PHBQSZytIoyuUK48Qw,759
1218
- vellum/workflows/events/node.py,sha256=QOikR6w5KXJUjnDNF2RhjXRbG7lJySetAoPamyr733Y,5264
1218
+ vellum/workflows/events/node.py,sha256=uHT6If0esgZ3nLjrjmUPTKf3qbjGhoV_x5YKpjDBDcU,5280
1219
1219
  vellum/workflows/events/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1220
- vellum/workflows/events/tests/test_event.py,sha256=EFg34nGpl_LvbHWN5AuiMqH6PetwGF_z0TlETGsn_bU,12725
1221
- vellum/workflows/events/types.py,sha256=7sBSMNstsibqq93Klu4A-GInzo4IB23xWel595Uyi_Y,3077
1222
- vellum/workflows/events/workflow.py,sha256=LW1qjLYCa9mpZjxp6YuDDA0M-q0COBIfLuduP9pOfyo,5224
1220
+ vellum/workflows/events/tests/test_event.py,sha256=izB6Y9U5ROgmHBBpLNUY2navK4-qFp6hdJqJNz6Beek,13350
1221
+ vellum/workflows/events/types.py,sha256=cjRE8WL8tYCFradd9NOGl_H0mN3LiWWnA1uHmyT2Q0Q,3412
1222
+ vellum/workflows/events/workflow.py,sha256=l5tXes0sg7iWaA1ZUE5dtAqNnGQ8iy6trVbOU9meu7U,5240
1223
1223
  vellum/workflows/exceptions.py,sha256=gXQvDL919cK3pwXc8BhLGKmR-YOskYDLvL1zPSSmLS4,579
1224
1224
  vellum/workflows/expressions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1225
1225
  vellum/workflows/expressions/accessor.py,sha256=OFvAHAVABr-k7GceIhtzIurV4OuV_yHft7JPRsq87Es,1472
@@ -1238,10 +1238,12 @@ vellum/workflows/expressions/greater_than.py,sha256=nMi6iAo0vi2hM3JeKfQSCy7DnXbd
1238
1238
  vellum/workflows/expressions/greater_than_or_equal_to.py,sha256=xUDjfsOrJdoWm9K7OafGDGsuyvYS3xbMjyV4umvA50Q,1164
1239
1239
  vellum/workflows/expressions/in_.py,sha256=tdDTvePdG4WyRkwmSaA4hsUdFJNiIMlrEG6oRrUskjI,1028
1240
1240
  vellum/workflows/expressions/is_blank.py,sha256=u8mGreoZb5t_q2mhhmpD7ytAfFCFUAW9APsDapqUsDY,809
1241
+ vellum/workflows/expressions/is_nil.py,sha256=dtgY9Czm3slk45weARspwtfhQmVh0BIUsPOECrATLrA,740
1241
1242
  vellum/workflows/expressions/is_not_blank.py,sha256=npXK9KSUm0nWeT6WJ5LLKB3owgBXHr7SpH8j4W0WapI,816
1242
- vellum/workflows/expressions/is_not_null.py,sha256=_vIwikSUnk6F3NVukV3-9FwoX38qUpTyvaY2oIBwURg,671
1243
+ vellum/workflows/expressions/is_not_nil.py,sha256=M5Qhtp_H07PORjFN2WapwA1Njp_KaANmLWbfckSSscM,761
1244
+ vellum/workflows/expressions/is_not_null.py,sha256=EoHXFgZScKP_BM2a5Z7YFQN6l7RMEtzs5x5nlvaSST8,671
1243
1245
  vellum/workflows/expressions/is_not_undefined.py,sha256=8NGwA0wZP_aHRy5qJOtaNhRCJyXKekwBNJalSk6Rdmo,727
1244
- vellum/workflows/expressions/is_null.py,sha256=5hj3WcFTxGS9ULcPP5BNJu683l0f5gq85Gvj2Nz6Utg,660
1246
+ vellum/workflows/expressions/is_null.py,sha256=C75ALGlG_sTGcxI46tm9HtgPVfJ7DwTIyKzX8qtEiDU,660
1245
1247
  vellum/workflows/expressions/is_undefined.py,sha256=c9Oc1fdp911fQQ8WMG2L-TeUSqz1wF8cOTuLutJKbe8,716
1246
1248
  vellum/workflows/expressions/less_than.py,sha256=DTWjbhaegnsCWnFSLNldTQr94Dqg3rqWOgMWI7IVsII,1149
1247
1249
  vellum/workflows/expressions/less_than_or_equal_to.py,sha256=IxP1VeXAzXrccdIWT2hm6Fj3Sr-7rPW-DKOHl6MrHjo,1161
@@ -1327,7 +1329,7 @@ vellum/workflows/nodes/displayable/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5
1327
1329
  vellum/workflows/nodes/displayable/tests/test_inline_text_prompt_node.py,sha256=lLnXKAUYtgvQ6MpT4GoTrqLtdlyDlUt1pPHrmu-Gf00,4705
1328
1330
  vellum/workflows/nodes/displayable/tests/test_search_node_wth_text_output.py,sha256=4CMwDtXwTaEvFfDpA6j2iLqc7S6IICSkvVZOobEpeps,6954
1329
1331
  vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py,sha256=KqKJtJ0vuNoPuUPMdILmBTt4a2fBBxxun-nmOI7T8jo,2585
1330
- vellum/workflows/nodes/utils.py,sha256=RWQbcc6MgxHNwFjtasY4hzIH8pKe0E3zfVt6eJKGTp4,587
1332
+ vellum/workflows/nodes/utils.py,sha256=EZt7CzJmgQBR_GWFpZr8d-oaoti3tolTd2Cv9wm7dKo,1087
1331
1333
  vellum/workflows/outputs/__init__.py,sha256=AyZ4pRh_ACQIGvkf0byJO46EDnSix1ZCAXfvh-ms1QE,94
1332
1334
  vellum/workflows/outputs/base.py,sha256=a7W6rNSDSawwGAXYjNTF2iHb9lnZu7WFSOagZIyy__k,7976
1333
1335
  vellum/workflows/ports/__init__.py,sha256=bZuMt-R7z5bKwpu4uPW7LlJeePOQWmCcDSXe5frUY5g,101
@@ -1375,10 +1377,10 @@ vellum/workflows/utils/uuids.py,sha256=DFzPv9RCvsKhvdTEIQyfSek2A31D6S_QcmeLPbgrg
1375
1377
  vellum/workflows/utils/vellum_variables.py,sha256=DsjVj_M_vTafpi5OUDs4KNrmbU2n4LR7fcLhuHb67Z4,3123
1376
1378
  vellum/workflows/vellum_client.py,sha256=ODrq_TSl-drX2aezXegf7pizpWDVJuTXH-j6528t75s,683
1377
1379
  vellum/workflows/workflows/__init__.py,sha256=KY45TqvavCCvXIkyCFMEc0dc6jTMOUci93U2DUrlZYc,66
1378
- vellum/workflows/workflows/base.py,sha256=jFu_AAyt4IqOrwanyflNnDhgYpX4oTVR5xnow8ynRhg,16811
1379
- vellum/workflows/workflows/event_filters.py,sha256=-uQcMB7IpPd-idMku8f2QNVhPXPFWo6FZLlGjRf8rCo,1996
1380
- vellum_ai-0.12.1.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1381
- vellum_ai-0.12.1.dist-info/METADATA,sha256=m7888sp693GSPQLWUuFa1W1ehpB2orR-RuEqmqpV-SQ,5128
1382
- vellum_ai-0.12.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1383
- vellum_ai-0.12.1.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1384
- vellum_ai-0.12.1.dist-info/RECORD,,
1380
+ vellum/workflows/workflows/base.py,sha256=zpspOEdO5Ye_0ZvN-Wkzv9iQSiF1sD201ba8lhbnPbs,17086
1381
+ vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnadGsrSZGa7t7LpJA,2008
1382
+ vellum_ai-0.12.3.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1383
+ vellum_ai-0.12.3.dist-info/METADATA,sha256=2LiLS000opig2vlfeENocV4Y7ekElNjRgEXVR9ddQIY,5128
1384
+ vellum_ai-0.12.3.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1385
+ vellum_ai-0.12.3.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1386
+ vellum_ai-0.12.3.dist-info/RECORD,,
@@ -1,6 +1,7 @@
1
1
  from uuid import UUID
2
2
  from typing import ClassVar, Dict, Optional
3
3
 
4
+ from vellum.workflows.nodes.utils import get_unadorned_node
4
5
  from vellum.workflows.ports import Port
5
6
  from vellum.workflows.types.generics import NodeType
6
7
  from vellum.workflows.utils.uuids import uuid4_from_hash
@@ -40,6 +41,8 @@ class BaseNodeVellumDisplay(BaseNodeDisplay[NodeType]):
40
41
  return self.get_target_handle_id()
41
42
 
42
43
  def get_source_handle_id(self, port_displays: Dict[Port, PortDisplay]) -> UUID:
43
- default_port = self._node.Ports.default
44
+ unadorned_node = get_unadorned_node(self._node)
45
+ default_port = unadorned_node.Ports.default
46
+
44
47
  default_port_display = port_displays[default_port]
45
48
  return default_port_display.id
@@ -16,8 +16,12 @@ from vellum.workflows.expressions.equals import EqualsExpression
16
16
  from vellum.workflows.expressions.greater_than import GreaterThanExpression
17
17
  from vellum.workflows.expressions.greater_than_or_equal_to import GreaterThanOrEqualToExpression
18
18
  from vellum.workflows.expressions.in_ import InExpression
19
+ from vellum.workflows.expressions.is_nil import IsNilExpression
20
+ from vellum.workflows.expressions.is_not_nil import IsNotNilExpression
19
21
  from vellum.workflows.expressions.is_not_null import IsNotNullExpression
22
+ from vellum.workflows.expressions.is_not_undefined import IsNotUndefinedExpression
20
23
  from vellum.workflows.expressions.is_null import IsNullExpression
24
+ from vellum.workflows.expressions.is_undefined import IsUndefinedExpression
21
25
  from vellum.workflows.expressions.less_than import LessThanExpression
22
26
  from vellum.workflows.expressions.less_than_or_equal_to import LessThanOrEqualToExpression
23
27
  from vellum.workflows.expressions.not_between import NotBetweenExpression
@@ -242,9 +246,9 @@ but the defined conditions have length {len(condition_ids)}"""
242
246
  return "doesNotBeginWith"
243
247
  elif isinstance(descriptor, DoesNotEndWithExpression):
244
248
  return "doesNotEndWith"
245
- elif isinstance(descriptor, IsNullExpression):
249
+ elif isinstance(descriptor, (IsNullExpression, IsNilExpression, IsUndefinedExpression)):
246
250
  return "null"
247
- elif isinstance(descriptor, IsNotNullExpression):
251
+ elif isinstance(descriptor, (IsNotNullExpression, IsNotNilExpression, IsNotUndefinedExpression)):
248
252
  return "notNull"
249
253
  elif isinstance(descriptor, InExpression):
250
254
  return "in"
@@ -1,9 +1,8 @@
1
1
  from uuid import UUID
2
- from typing import ClassVar, Dict, Generic, List, Optional, Tuple, Type, TypeVar, Union, cast
2
+ from typing import ClassVar, Dict, Generic, List, Optional, Tuple, Type, TypeVar, Union
3
3
 
4
4
  from vellum import PromptBlock, RichTextChildBlock, VellumVariable
5
5
  from vellum.workflows.nodes import InlinePromptNode
6
- from vellum.workflows.references import OutputReference
7
6
  from vellum.workflows.types.core import JsonObject
8
7
  from vellum.workflows.utils.uuids import uuid4_from_hash
9
8
  from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
@@ -30,8 +29,8 @@ class BaseInlinePromptNodeDisplay(BaseNodeVellumDisplay[_InlinePromptNodeType],
30
29
  node_inputs, prompt_inputs = self._generate_node_and_prompt_inputs(node_id, node, display_context)
31
30
  input_variable_id_by_name = {prompt_input.key: prompt_input.id for prompt_input in prompt_inputs}
32
31
 
33
- _, output_display = display_context.node_output_displays[cast(OutputReference, node.Outputs.text)]
34
- _, array_display = display_context.node_output_displays[cast(OutputReference, node.Outputs.results)]
32
+ _, output_display = display_context.node_output_displays[node.Outputs.text]
33
+ _, array_display = display_context.node_output_displays[node.Outputs.results]
35
34
  node_blocks = raise_if_descriptor(node.blocks)
36
35
 
37
36
  return {
@@ -1,11 +1,13 @@
1
1
  from uuid import UUID
2
- from typing import Any, ClassVar, Generic, Optional, TypeVar
2
+ from typing import Any, Callable, ClassVar, Generic, Optional, Type, TypeVar, cast
3
3
 
4
4
  from vellum.workflows.nodes.bases.base import BaseNode
5
5
  from vellum.workflows.nodes.core.try_node.node import TryNode
6
6
  from vellum.workflows.nodes.utils import ADORNMENT_MODULE_NAME, get_wrapped_node
7
7
  from vellum.workflows.types.core import JsonObject
8
+ from vellum.workflows.types.utils import get_original_base
8
9
  from vellum.workflows.utils.uuids import uuid4_from_hash
10
+ from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
9
11
  from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
10
12
  from vellum_ee.workflows.display.nodes.get_node_display_class import get_node_display_class
11
13
  from vellum_ee.workflows.display.nodes.utils import raise_if_descriptor
@@ -54,3 +56,43 @@ class BaseTryNodeDisplay(BaseNodeVellumDisplay[_TryNodeType], Generic[_TryNodeTy
54
56
  serialized_node_definition["name"] = node.__name__
55
57
 
56
58
  return serialized_node
59
+
60
+ @classmethod
61
+ def wrap(cls, error_output_id: Optional[UUID] = None) -> Callable[..., Type["BaseTryNodeDisplay"]]:
62
+ _error_output_id = error_output_id
63
+
64
+ NodeDisplayType = TypeVar("NodeDisplayType", bound=BaseNodeDisplay)
65
+
66
+ def decorator(inner_cls: Type[NodeDisplayType]) -> Type[NodeDisplayType]:
67
+ node_class = inner_cls.infer_node_class()
68
+ wrapped_node_class = cast(Type[BaseNode], node_class.__wrapped_node__)
69
+
70
+ # Mypy gets mad about dynamic parameter types like this, but it's fine
71
+ class TryNodeDisplay(BaseTryNodeDisplay[node_class]): # type: ignore[valid-type]
72
+ error_output_id = _error_output_id
73
+
74
+ setattr(inner_cls, "__adorned_by__", TryNodeDisplay)
75
+
76
+ # We must edit the node display class to use __wrapped_node__ everywhere it
77
+ # references the adorned node class, which is three places:
78
+
79
+ # 1. The node display class' parameterized type
80
+ original_base_node_display = get_original_base(inner_cls)
81
+ original_base_node_display.__args__ = (wrapped_node_class,)
82
+ inner_cls._node_display_registry[wrapped_node_class] = inner_cls
83
+
84
+ # 2. The node display class' output displays
85
+ old_outputs = list(inner_cls.output_display.keys())
86
+ for old_output in old_outputs:
87
+ new_output = getattr(wrapped_node_class.Outputs, old_output.name)
88
+ inner_cls.output_display[new_output] = inner_cls.output_display.pop(old_output)
89
+
90
+ # 3. The node display class' port displays
91
+ old_ports = list(inner_cls.port_displays.keys())
92
+ for old_port in old_ports:
93
+ new_port = getattr(wrapped_node_class.Ports, old_port.name)
94
+ inner_cls.port_displays[new_port] = inner_cls.port_displays.pop(old_port)
95
+
96
+ return inner_cls
97
+
98
+ return decorator
@@ -6,7 +6,7 @@ from vellum.workflows.descriptors.base import BaseDescriptor
6
6
  from vellum.workflows.edges import Edge
7
7
  from vellum.workflows.nodes.bases import BaseNode
8
8
  from vellum.workflows.nodes.displayable.final_output_node import FinalOutputNode
9
- from vellum.workflows.nodes.utils import get_wrapped_node, has_wrapped_node
9
+ from vellum.workflows.nodes.utils import get_unadorned_node, get_unadorned_port, get_wrapped_node, has_wrapped_node
10
10
  from vellum.workflows.ports import Port
11
11
  from vellum.workflows.references import WorkflowInputReference
12
12
  from vellum.workflows.references.output import OutputReference
@@ -352,17 +352,12 @@ class VellumWorkflowDisplay(
352
352
  port_displays: Dict[Port, PortDisplay],
353
353
  overrides: Optional[EdgeVellumDisplayOverrides] = None,
354
354
  ) -> EdgeVellumDisplay:
355
- source_node = edge.from_port.node_class
356
- target_node = edge.to_node
357
-
358
- if has_wrapped_node(source_node):
359
- source_node = get_wrapped_node(source_node)
360
-
361
- if has_wrapped_node(target_node):
362
- target_node = get_wrapped_node(target_node)
355
+ source_node = get_unadorned_node(edge.from_port.node_class)
356
+ target_node = get_unadorned_node(edge.to_node)
363
357
 
364
358
  source_node_id = node_displays[source_node].node_id
365
- source_handle_id = port_displays[edge.from_port].id
359
+ from_port = get_unadorned_port(edge.from_port)
360
+ source_handle_id = port_displays[from_port].id
366
361
 
367
362
  target_node_display = node_displays[target_node]
368
363
  target_node_id = target_node_display.node_id