vellum-ai 0.13.8__py3-none-any.whl → 0.13.10__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 (49) hide show
  1. vellum/client/core/client_wrapper.py +1 -1
  2. vellum/plugins/vellum_mypy.py +6 -2
  3. vellum/workflows/descriptors/utils.py +1 -1
  4. vellum/workflows/nodes/bases/base.py +1 -2
  5. vellum/workflows/nodes/displayable/api_node/node.py +4 -1
  6. vellum/workflows/nodes/displayable/bases/api_node/node.py +4 -1
  7. vellum/workflows/nodes/displayable/bases/base_prompt_node/node.py +4 -1
  8. vellum/workflows/nodes/displayable/bases/inline_prompt_node/node.py +4 -0
  9. vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +4 -0
  10. vellum/workflows/nodes/displayable/bases/search_node.py +4 -0
  11. vellum/workflows/nodes/displayable/code_execution_node/node.py +4 -1
  12. vellum/workflows/nodes/displayable/conditional_node/node.py +4 -0
  13. vellum/workflows/nodes/displayable/final_output_node/node.py +4 -0
  14. vellum/workflows/nodes/displayable/guardrail_node/node.py +4 -1
  15. vellum/workflows/nodes/displayable/inline_prompt_node/node.py +4 -0
  16. vellum/workflows/nodes/displayable/merge_node/node.py +3 -1
  17. vellum/workflows/nodes/displayable/note_node/node.py +4 -0
  18. vellum/workflows/nodes/displayable/prompt_deployment_node/node.py +4 -0
  19. vellum/workflows/nodes/displayable/search_node/node.py +4 -0
  20. vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +4 -1
  21. vellum/workflows/nodes/utils.py +6 -18
  22. {vellum_ai-0.13.8.dist-info → vellum_ai-0.13.10.dist-info}/METADATA +1 -1
  23. {vellum_ai-0.13.8.dist-info → vellum_ai-0.13.10.dist-info}/RECORD +49 -48
  24. vellum_ee/workflows/display/nodes/base_node_display.py +103 -3
  25. vellum_ee/workflows/display/nodes/vellum/base_node.py +34 -105
  26. vellum_ee/workflows/display/nodes/vellum/conditional_node.py +2 -1
  27. vellum_ee/workflows/display/nodes/vellum/tests/test_try_node.py +63 -0
  28. vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py +3 -4
  29. vellum_ee/workflows/display/nodes/vellum/try_node.py +28 -4
  30. vellum_ee/workflows/display/nodes/vellum/utils.py +1 -80
  31. vellum_ee/workflows/display/tests/test_vellum_workflow_display.py +56 -0
  32. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py +3 -2
  33. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +143 -26
  34. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +10 -10
  35. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_outputs_serialization.py +6 -6
  36. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_ports_serialization.py +32 -34
  37. vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_trigger_serialization.py +4 -4
  38. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +1 -2
  39. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +5 -5
  40. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py +1 -1
  41. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +6 -3
  42. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +6 -3
  43. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +3 -3
  44. vellum_ee/workflows/display/utils/vellum.py +74 -4
  45. vellum_ee/workflows/display/workflows/base_workflow_display.py +22 -24
  46. vellum_ee/workflows/display/workflows/vellum_workflow_display.py +6 -15
  47. {vellum_ai-0.13.8.dist-info → vellum_ai-0.13.10.dist-info}/LICENSE +0 -0
  48. {vellum_ai-0.13.8.dist-info → vellum_ai-0.13.10.dist-info}/WHEEL +0 -0
  49. {vellum_ai-0.13.8.dist-info → vellum_ai-0.13.10.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.13.8",
21
+ "X-Fern-SDK-Version": "0.13.10",
22
22
  }
23
23
  headers["X_API_KEY"] = self.api_key
24
24
  return headers
@@ -19,6 +19,7 @@ from mypy.plugin import AttributeContext, ClassDefContext, FunctionSigContext, M
19
19
  from mypy.types import AnyType, CallableType, FunctionLike, Instance, Type as MypyType, TypeAliasType, UnionType
20
20
 
21
21
  TypeResolver = Callable[[str, List[MypyType]], MypyType]
22
+ NODE_ATTRIBUTE_REGEX = r"^[a-z].*$"
22
23
 
23
24
  DESCRIPTOR_PATHS: list[tuple[str, str, str]] = [
24
25
  (
@@ -49,7 +50,7 @@ DESCRIPTOR_PATHS: list[tuple[str, str, str]] = [
49
50
  (
50
51
  "vellum.workflows.nodes.bases.base.BaseNode",
51
52
  "vellum.workflows.references.node.NodeReference",
52
- r"^[a-z].*$",
53
+ NODE_ATTRIBUTE_REGEX,
53
54
  ),
54
55
  ]
55
56
 
@@ -239,10 +240,13 @@ class VellumMypyPlugin(Plugin):
239
240
  the original defined type, and the descriptor version of the type.
240
241
  """
241
242
 
242
- for sym in ctx.cls.info.names.values():
243
+ for key, sym in ctx.cls.info.names.items():
243
244
  if not isinstance(sym.node, Var):
244
245
  continue
245
246
 
247
+ if not re.match(NODE_ATTRIBUTE_REGEX, key):
248
+ continue
249
+
246
250
  type_ = sym.node.type
247
251
  if not type_:
248
252
  continue
@@ -108,7 +108,7 @@ def is_unresolved(value: Any) -> bool:
108
108
  if isinstance(value, Mapping):
109
109
  return any(is_unresolved(item) for item in value.values())
110
110
 
111
- if isinstance(value, Sequence):
111
+ if isinstance(value, Sequence) and not isinstance(value, str):
112
112
  return any(is_unresolved(item) for item in value)
113
113
 
114
114
  if isinstance(value, Set):
@@ -222,7 +222,6 @@ class BaseNode(Generic[StateType], metaclass=BaseNodeMeta):
222
222
  state: StateType
223
223
  _context: WorkflowContext
224
224
  _inputs: MappingProxyType[NodeReference, Any]
225
- _is_wrapped_node: bool = False
226
225
 
227
226
  class ExternalInputs(BaseInputs):
228
227
  __descriptor_class__ = ExternalInputReference
@@ -238,7 +237,7 @@ class BaseNode(Generic[StateType], metaclass=BaseNodeMeta):
238
237
 
239
238
  class Trigger(metaclass=_BaseNodeTriggerMeta):
240
239
  node_class: Type["BaseNode"]
241
- merge_behavior = MergeBehavior.AWAIT_ANY
240
+ merge_behavior = MergeBehavior.AWAIT_ATTRIBUTES
242
241
 
243
242
  @classmethod
244
243
  def should_initiate(
@@ -2,7 +2,7 @@ from typing import Optional, Union
2
2
 
3
3
  from vellum.workflows.constants import AuthorizationType
4
4
  from vellum.workflows.nodes.displayable.bases.api_node import BaseAPINode
5
- from vellum.workflows.types.core import VellumSecret
5
+ from vellum.workflows.types.core import MergeBehavior, VellumSecret
6
6
 
7
7
 
8
8
  class APINode(BaseAPINode):
@@ -27,6 +27,9 @@ class APINode(BaseAPINode):
27
27
  api_key_header_value: Optional[Union[str, VellumSecret]] = None
28
28
  bearer_token_value: Optional[Union[str, VellumSecret]] = None
29
29
 
30
+ class Trigger(BaseAPINode.Trigger):
31
+ merge_behavior = MergeBehavior.AWAIT_ANY
32
+
30
33
  def run(self) -> BaseAPINode.Outputs:
31
34
  headers = self.headers or {}
32
35
  header_overrides = {}
@@ -8,7 +8,7 @@ from vellum.workflows.errors.types import WorkflowErrorCode
8
8
  from vellum.workflows.exceptions import NodeException
9
9
  from vellum.workflows.nodes.bases import BaseNode
10
10
  from vellum.workflows.outputs import BaseOutputs
11
- from vellum.workflows.types.core import Json, VellumSecret
11
+ from vellum.workflows.types.core import Json, MergeBehavior, VellumSecret
12
12
  from vellum.workflows.types.generics import StateType
13
13
 
14
14
 
@@ -23,6 +23,9 @@ class BaseAPINode(BaseNode, Generic[StateType]):
23
23
  headers: Optional[Dict[str, Union[str, VellumSecret]]] - The headers to send in the request.
24
24
  """
25
25
 
26
+ class Trigger(BaseNode.Trigger):
27
+ merge_behavior = MergeBehavior.AWAIT_ANY
28
+
26
29
  url: str
27
30
  method: APIRequestMethod
28
31
  data: Optional[str] = None
@@ -7,7 +7,7 @@ from vellum.workflows.errors.types import WorkflowErrorCode, vellum_error_to_wor
7
7
  from vellum.workflows.exceptions import NodeException
8
8
  from vellum.workflows.nodes.bases import BaseNode
9
9
  from vellum.workflows.outputs.base import BaseOutput, BaseOutputs
10
- from vellum.workflows.types.core import EntityInputsInterface
10
+ from vellum.workflows.types.core import EntityInputsInterface, MergeBehavior
11
11
  from vellum.workflows.types.generics import StateType
12
12
 
13
13
 
@@ -17,6 +17,9 @@ class BasePromptNode(BaseNode, Generic[StateType]):
17
17
 
18
18
  request_options: Optional[RequestOptions] = None
19
19
 
20
+ class Trigger(BaseNode.Trigger):
21
+ merge_behavior = MergeBehavior.AWAIT_ANY
22
+
20
23
  class Outputs(BaseOutputs):
21
24
  results: List[PromptOutput]
22
25
 
@@ -23,6 +23,7 @@ from vellum.workflows.events.types import default_serializer
23
23
  from vellum.workflows.exceptions import NodeException
24
24
  from vellum.workflows.nodes.displayable.bases.base_prompt_node import BasePromptNode
25
25
  from vellum.workflows.nodes.displayable.bases.inline_prompt_node.constants import DEFAULT_PROMPT_PARAMETERS
26
+ from vellum.workflows.types import MergeBehavior
26
27
  from vellum.workflows.types.generics import StateType
27
28
  from vellum.workflows.utils.functions import compile_function_definition
28
29
 
@@ -51,6 +52,9 @@ class BaseInlinePromptNode(BasePromptNode[StateType], Generic[StateType]):
51
52
  parameters: PromptParameters = DEFAULT_PROMPT_PARAMETERS
52
53
  expand_meta: Optional[AdHocExpandMeta] = OMIT
53
54
 
55
+ class Trigger(BasePromptNode.Trigger):
56
+ merge_behavior = MergeBehavior.AWAIT_ANY
57
+
54
58
  def _get_prompt_event_stream(self) -> Iterator[AdHocExecutePromptEvent]:
55
59
  input_variables, input_values = self._compile_prompt_inputs()
56
60
  parent_context = get_parent_context()
@@ -17,6 +17,7 @@ from vellum.workflows.context import get_parent_context
17
17
  from vellum.workflows.errors import WorkflowErrorCode
18
18
  from vellum.workflows.exceptions import NodeException
19
19
  from vellum.workflows.nodes.displayable.bases.base_prompt_node import BasePromptNode
20
+ from vellum.workflows.types import MergeBehavior
20
21
  from vellum.workflows.types.generics import StateType
21
22
 
22
23
 
@@ -47,6 +48,9 @@ class BasePromptDeploymentNode(BasePromptNode, Generic[StateType]):
47
48
  expand_raw: Optional[Sequence[str]] = OMIT
48
49
  metadata: Optional[Dict[str, Optional[Any]]] = OMIT
49
50
 
51
+ class Trigger(BasePromptNode.Trigger):
52
+ merge_behavior = MergeBehavior.AWAIT_ANY
53
+
50
54
  def _get_prompt_event_stream(self) -> Iterator[ExecutePromptEvent]:
51
55
  current_parent_context = get_parent_context()
52
56
  parent_context = current_parent_context.model_dump() if current_parent_context else None
@@ -17,6 +17,7 @@ from vellum.workflows.exceptions import NodeException
17
17
  from vellum.workflows.nodes.bases import BaseNode
18
18
  from vellum.workflows.nodes.displayable.bases.types import SearchFilters
19
19
  from vellum.workflows.outputs import BaseOutputs
20
+ from vellum.workflows.types import MergeBehavior
20
21
  from vellum.workflows.types.generics import StateType
21
22
 
22
23
  DEFAULT_SEARCH_WEIGHTS = 0.8
@@ -81,6 +82,9 @@ class BaseSearchNode(BaseNode[StateType], Generic[StateType]):
81
82
 
82
83
  request_options: Optional[RequestOptions] = None
83
84
 
85
+ class Trigger(BaseNode.Trigger):
86
+ merge_behavior = MergeBehavior.AWAIT_ANY
87
+
84
88
  class Outputs(BaseOutputs):
85
89
  """
86
90
  The outputs of the SearchNode.
@@ -26,7 +26,7 @@ from vellum.workflows.nodes.bases import BaseNode
26
26
  from vellum.workflows.nodes.bases.base import BaseNodeMeta
27
27
  from vellum.workflows.nodes.displayable.code_execution_node.utils import read_file_from_path
28
28
  from vellum.workflows.outputs.base import BaseOutputs
29
- from vellum.workflows.types.core import EntityInputsInterface, VellumSecret
29
+ from vellum.workflows.types.core import EntityInputsInterface, MergeBehavior, VellumSecret
30
30
  from vellum.workflows.types.generics import StateType
31
31
  from vellum.workflows.types.utils import get_original_base
32
32
  from vellum.workflows.utils.vellum_variables import primitive_type_to_vellum_variable_type
@@ -82,6 +82,9 @@ class CodeExecutionNode(BaseNode[StateType], Generic[StateType, _OutputType], me
82
82
 
83
83
  request_options: Optional[RequestOptions] = None
84
84
 
85
+ class Trigger(BaseNode.Trigger):
86
+ merge_behavior = MergeBehavior.AWAIT_ANY
87
+
85
88
  class Outputs(BaseOutputs):
86
89
  # We use our mypy plugin to override the _OutputType with the actual output type
87
90
  # for downstream references to this output.
@@ -6,6 +6,7 @@ from vellum.workflows.ports.node_ports import NodePorts
6
6
  from vellum.workflows.ports.port import Port
7
7
  from vellum.workflows.ports.utils import validate_ports
8
8
  from vellum.workflows.state.base import BaseState
9
+ from vellum.workflows.types import MergeBehavior
9
10
 
10
11
 
11
12
  class ConditionalNode(BaseNode):
@@ -14,6 +15,9 @@ class ConditionalNode(BaseNode):
14
15
  Vellum's Conditional Node, and for most cases, you should extend `BaseNode.Ports` directly.
15
16
  """
16
17
 
18
+ class Trigger(BaseNode.Trigger):
19
+ merge_behavior = MergeBehavior.AWAIT_ANY
20
+
17
21
  class Ports(NodePorts):
18
22
  def __call__(self, outputs: BaseOutputs, state: BaseState) -> Set[Port]:
19
23
  all_ports = [port for port in self.__class__]
@@ -2,6 +2,7 @@ from typing import Any, Dict, Generic, Tuple, Type, TypeVar, get_args
2
2
 
3
3
  from vellum.workflows.nodes.bases import BaseNode
4
4
  from vellum.workflows.nodes.bases.base import BaseNodeMeta
5
+ from vellum.workflows.types import MergeBehavior
5
6
  from vellum.workflows.types.generics import StateType
6
7
  from vellum.workflows.types.utils import get_original_base
7
8
 
@@ -41,6 +42,9 @@ class FinalOutputNode(BaseNode[StateType], Generic[StateType, _OutputType], meta
41
42
  This provides backward compatibility with Vellum's Final Output Node.
42
43
  """
43
44
 
45
+ class Trigger(BaseNode.Trigger):
46
+ merge_behavior = MergeBehavior.AWAIT_ANY
47
+
44
48
  class Outputs(BaseNode.Outputs):
45
49
  # We use our mypy plugin to override the _OutputType with the actual output type
46
50
  # for downstream references to this output.
@@ -8,7 +8,7 @@ from vellum.workflows.errors.types import WorkflowErrorCode
8
8
  from vellum.workflows.exceptions import NodeException
9
9
  from vellum.workflows.nodes.bases import BaseNode
10
10
  from vellum.workflows.outputs.base import BaseOutputs
11
- from vellum.workflows.types.core import EntityInputsInterface
11
+ from vellum.workflows.types.core import EntityInputsInterface, MergeBehavior
12
12
  from vellum.workflows.types.generics import StateType
13
13
 
14
14
 
@@ -29,6 +29,9 @@ class GuardrailNode(BaseNode[StateType], Generic[StateType]):
29
29
 
30
30
  request_options: Optional[RequestOptions] = None
31
31
 
32
+ class Trigger(BaseNode.Trigger):
33
+ merge_behavior = MergeBehavior.AWAIT_ANY
34
+
32
35
  class Outputs(BaseOutputs):
33
36
  score: float
34
37
 
@@ -5,6 +5,7 @@ from vellum.workflows.errors import WorkflowErrorCode
5
5
  from vellum.workflows.exceptions import NodeException
6
6
  from vellum.workflows.nodes.displayable.bases import BaseInlinePromptNode as BaseInlinePromptNode
7
7
  from vellum.workflows.outputs import BaseOutput
8
+ from vellum.workflows.types import MergeBehavior
8
9
  from vellum.workflows.types.generics import StateType
9
10
 
10
11
 
@@ -21,6 +22,9 @@ class InlinePromptNode(BaseInlinePromptNode[StateType]):
21
22
  request_options: Optional[RequestOptions] - The request options to use for the Prompt Execution
22
23
  """
23
24
 
25
+ class Trigger(BaseInlinePromptNode.Trigger):
26
+ merge_behavior = MergeBehavior.AWAIT_ANY
27
+
24
28
  class Outputs(BaseInlinePromptNode.Outputs):
25
29
  """
26
30
  The outputs of the InlinePromptNode.
@@ -1,4 +1,5 @@
1
1
  from vellum.workflows.nodes.bases import BaseNode
2
+ from vellum.workflows.types import MergeBehavior
2
3
 
3
4
 
4
5
  class MergeNode(BaseNode):
@@ -7,4 +8,5 @@ class MergeNode(BaseNode):
7
8
  with Vellum's Merge Node, and for most cases, you should extend from `BaseNode.Trigger` directly.
8
9
  """
9
10
 
10
- pass
11
+ class Trigger(BaseNode.Trigger):
12
+ merge_behavior = MergeBehavior.AWAIT_ANY
@@ -1,4 +1,5 @@
1
1
  from vellum.workflows.nodes.bases import BaseNode
2
+ from vellum.workflows.types import MergeBehavior
2
3
 
3
4
 
4
5
  class NoteNode(BaseNode):
@@ -6,5 +7,8 @@ class NoteNode(BaseNode):
6
7
  A no-op Node purely used to display a note in the Vellum UI.
7
8
  """
8
9
 
10
+ class Trigger(BaseNode.Trigger):
11
+ merge_behavior = MergeBehavior.AWAIT_ANY
12
+
9
13
  def run(self) -> BaseNode.Outputs:
10
14
  raise RuntimeError("NoteNode should never be run")
@@ -4,6 +4,7 @@ from vellum.workflows.errors import WorkflowErrorCode
4
4
  from vellum.workflows.exceptions import NodeException
5
5
  from vellum.workflows.nodes.displayable.bases import BasePromptDeploymentNode as BasePromptDeploymentNode
6
6
  from vellum.workflows.outputs import BaseOutput
7
+ from vellum.workflows.types import MergeBehavior
7
8
  from vellum.workflows.types.generics import StateType
8
9
 
9
10
 
@@ -23,6 +24,9 @@ class PromptDeploymentNode(BasePromptDeploymentNode[StateType]):
23
24
  request_options: Optional[RequestOptions] - The request options to use for the Prompt Execution
24
25
  """
25
26
 
27
+ class Trigger(BasePromptDeploymentNode.Trigger):
28
+ merge_behavior = MergeBehavior.AWAIT_ANY
29
+
26
30
  class Outputs(BasePromptDeploymentNode.Outputs):
27
31
  """
28
32
  The outputs of the PromptDeploymentNode.
@@ -1,6 +1,7 @@
1
1
  from typing import ClassVar
2
2
 
3
3
  from vellum.workflows.nodes.displayable.bases import BaseSearchNode as BaseSearchNode
4
+ from vellum.workflows.types import MergeBehavior
4
5
  from vellum.workflows.types.generics import StateType
5
6
 
6
7
 
@@ -18,6 +19,9 @@ class SearchNode(BaseSearchNode[StateType]):
18
19
 
19
20
  chunk_separator: ClassVar[str] = "\n\n#####\n\n"
20
21
 
22
+ class Trigger(BaseSearchNode.Trigger):
23
+ merge_behavior = MergeBehavior.AWAIT_ANY
24
+
21
25
  class Outputs(BaseSearchNode.Outputs):
22
26
  """
23
27
  The outputs of the SearchNode.
@@ -19,7 +19,7 @@ from vellum.workflows.errors.types import workflow_event_error_to_workflow_error
19
19
  from vellum.workflows.exceptions import NodeException
20
20
  from vellum.workflows.nodes.bases.base import BaseNode
21
21
  from vellum.workflows.outputs.base import BaseOutput
22
- from vellum.workflows.types.core import EntityInputsInterface
22
+ from vellum.workflows.types.core import EntityInputsInterface, MergeBehavior
23
23
  from vellum.workflows.types.generics import StateType
24
24
 
25
25
 
@@ -49,6 +49,9 @@ class SubworkflowDeploymentNode(BaseNode[StateType], Generic[StateType]):
49
49
 
50
50
  request_options: Optional[RequestOptions] = None
51
51
 
52
+ class Trigger(BaseNode.Trigger):
53
+ merge_behavior = MergeBehavior.AWAIT_ANY
54
+
52
55
  def _compile_subworkflow_inputs(self) -> List[WorkflowRequestInputRequest]:
53
56
  # TODO: We may want to consolidate with prompt deployment input compilation
54
57
  # https://app.shortcut.com/vellum/story/4117
@@ -4,6 +4,7 @@ from types import ModuleType
4
4
  from typing import Any, Callable, Optional, Type, TypeVar
5
5
 
6
6
  from vellum.workflows.nodes import BaseNode
7
+ from vellum.workflows.nodes.bases.base_adornment_node import BaseAdornmentNode
7
8
  from vellum.workflows.ports.port import Port
8
9
  from vellum.workflows.types.generics import NodeType
9
10
 
@@ -12,7 +13,7 @@ ADORNMENT_MODULE_NAME = "<adornment>"
12
13
 
13
14
  @cache
14
15
  def get_unadorned_node(node: Type[BaseNode]) -> Type[BaseNode]:
15
- wrapped_node = getattr(node, "__wrapped_node__", None)
16
+ wrapped_node = get_wrapped_node(node)
16
17
  if wrapped_node is not None:
17
18
  return get_unadorned_node(wrapped_node)
18
19
 
@@ -28,22 +29,11 @@ def get_unadorned_port(port: Port) -> Port:
28
29
  return getattr(unadorned_node.Ports, port.name)
29
30
 
30
31
 
31
- @cache
32
- def get_wrapped_node(node: Type[NodeType]) -> Type[BaseNode]:
33
- wrapped_node = getattr(node, "__wrapped_node__", None)
34
- if wrapped_node is None:
35
- raise AttributeError("Wrapped node not found")
36
-
37
- return wrapped_node
38
-
32
+ def get_wrapped_node(node: Type[NodeType]) -> Optional[Type[BaseNode]]:
33
+ if not issubclass(node, BaseAdornmentNode):
34
+ return None
39
35
 
40
- def has_wrapped_node(node: Type[NodeType]) -> bool:
41
- try:
42
- get_wrapped_node(node)
43
- except AttributeError:
44
- return False
45
-
46
- return True
36
+ return node.__wrapped_node__
47
37
 
48
38
 
49
39
  AdornableNode = TypeVar("AdornableNode", bound=BaseNode)
@@ -57,8 +47,6 @@ def create_adornment(
57
47
  # https://app.shortcut.com/vellum/story/4116
58
48
  from vellum.workflows import BaseWorkflow
59
49
 
60
- inner_cls._is_wrapped_node = True
61
-
62
50
  class Subworkflow(BaseWorkflow):
63
51
  graph = inner_cls
64
52
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vellum-ai
3
- Version: 0.13.8
3
+ Version: 0.13.10
4
4
  Summary:
5
5
  License: MIT
6
6
  Requires-Python: >=3.9,<4.0