vellum-ai 0.13.20__py3-none-any.whl → 0.13.21__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.
@@ -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.20",
21
+ "X-Fern-SDK-Version": "0.13.21",
22
22
  }
23
23
  headers["X_API_KEY"] = self.api_key
24
24
  return headers
@@ -6,7 +6,7 @@ from vellum.core.pydantic_utilities import UniversalBaseModel
6
6
  from vellum.workflows.errors import WorkflowError
7
7
  from vellum.workflows.outputs.base import BaseOutput
8
8
  from vellum.workflows.references import ExternalInputReference
9
- from vellum.workflows.types.generics import OutputsType, StateType, WorkflowInputsType
9
+ from vellum.workflows.types.generics import InputsType, OutputsType, StateType
10
10
 
11
11
  from .node import (
12
12
  NodeExecutionFulfilledEvent,
@@ -38,20 +38,20 @@ class _BaseWorkflowEvent(BaseEvent):
38
38
  return self.body.workflow_definition
39
39
 
40
40
 
41
- class WorkflowExecutionInitiatedBody(_BaseWorkflowExecutionBody, Generic[WorkflowInputsType]):
42
- inputs: WorkflowInputsType
41
+ class WorkflowExecutionInitiatedBody(_BaseWorkflowExecutionBody, Generic[InputsType]):
42
+ inputs: InputsType
43
43
 
44
44
  @field_serializer("inputs")
45
- def serialize_inputs(self, inputs: WorkflowInputsType, _info: Any) -> Dict[str, Any]:
45
+ def serialize_inputs(self, inputs: InputsType, _info: Any) -> Dict[str, Any]:
46
46
  return default_serializer(inputs)
47
47
 
48
48
 
49
- class WorkflowExecutionInitiatedEvent(_BaseWorkflowEvent, Generic[WorkflowInputsType]):
49
+ class WorkflowExecutionInitiatedEvent(_BaseWorkflowEvent, Generic[InputsType]):
50
50
  name: Literal["workflow.execution.initiated"] = "workflow.execution.initiated"
51
- body: WorkflowExecutionInitiatedBody[WorkflowInputsType]
51
+ body: WorkflowExecutionInitiatedBody[InputsType]
52
52
 
53
53
  @property
54
- def inputs(self) -> WorkflowInputsType:
54
+ def inputs(self) -> InputsType:
55
55
  return self.body.inputs
56
56
 
57
57
 
@@ -118,6 +118,12 @@ class Graph:
118
118
  self._terminals = {other}
119
119
  return self
120
120
 
121
+ def __rrshift__(cls, other_cls: GraphTarget) -> "Graph":
122
+ if not isinstance(other_cls, set):
123
+ other_cls = {other_cls}
124
+
125
+ return Graph.from_set(other_cls) >> cls
126
+
121
127
  @property
122
128
  def entrypoints(self) -> Iterator[Type["BaseNode"]]:
123
129
  return iter(e.node_class for e in self._entrypoints)
@@ -460,3 +460,27 @@ def test_graph__node_to_port():
460
460
 
461
461
  # AND two edges
462
462
  assert len(list(graph.edges)) == 2
463
+
464
+
465
+ def test_graph__set_to_graph():
466
+ # GIVEN three nodes
467
+ class SourceNode(BaseNode):
468
+ pass
469
+
470
+ class MiddleNode(BaseNode):
471
+ pass
472
+
473
+ class TargetNode(BaseNode):
474
+ pass
475
+
476
+ # WHEN we create a graph from a set to a graph
477
+ graph: Graph = {SourceNode, MiddleNode} >> Graph.from_node(TargetNode)
478
+
479
+ # THEN the graph has the source node and middle node as the entrypoints
480
+ assert set(graph.entrypoints) == {SourceNode, MiddleNode}
481
+
482
+ # AND three nodes
483
+ assert len(list(graph.nodes)) == 3
484
+
485
+ # AND two edges
486
+ assert len(list(graph.edges)) == 2
@@ -1,3 +1,4 @@
1
+ from dataclasses import field
1
2
  from functools import cached_property, reduce
2
3
  import inspect
3
4
  from types import MappingProxyType
@@ -192,7 +193,7 @@ class _BaseNodeTriggerMeta(type):
192
193
 
193
194
  class _BaseNodeExecutionMeta(type):
194
195
  def __getattribute__(cls, name: str) -> Any:
195
- if name.startswith("count") and issubclass(cls, BaseNode.Execution):
196
+ if name == "count" and issubclass(cls, BaseNode.Execution):
196
197
  return ExecutionCountReference(cls.node_class)
197
198
 
198
199
  return super().__getattribute__(name)
@@ -230,7 +231,7 @@ class BaseNode(Generic[StateType], metaclass=BaseNodeMeta):
230
231
  # "Outputs" class inherits from "BaseOutputs" and do so automatically.
231
232
  # https://app.shortcut.com/vellum/story/4008/auto-inherit-basenodeoutputs-in-outputs-classes
232
233
  class Outputs(BaseOutputs):
233
- _node_class: Optional[Type["BaseNode"]] = None
234
+ _node_class: Type["BaseNode"] = field(init=False)
234
235
 
235
236
  class Ports(NodePorts):
236
237
  default = Port(default=True)
@@ -11,7 +11,7 @@ from vellum.workflows.references import OutputReference
11
11
  from vellum.workflows.state.base import BaseState
12
12
  from vellum.workflows.state.context import WorkflowContext
13
13
  from vellum.workflows.types.core import EntityInputsInterface
14
- from vellum.workflows.types.generics import StateType, WorkflowInputsType
14
+ from vellum.workflows.types.generics import InputsType, StateType
15
15
  from vellum.workflows.workflows.event_filters import all_workflow_event_filter
16
16
 
17
17
  if TYPE_CHECKING:
@@ -57,16 +57,16 @@ class _InlineSubworkflowNodeMeta(BaseNodeMeta):
57
57
 
58
58
 
59
59
  class InlineSubworkflowNode(
60
- BaseNode[StateType], Generic[StateType, WorkflowInputsType, InnerStateType], metaclass=_InlineSubworkflowNodeMeta
60
+ BaseNode[StateType], Generic[StateType, InputsType, InnerStateType], metaclass=_InlineSubworkflowNodeMeta
61
61
  ):
62
62
  """
63
63
  Used to execute a Subworkflow defined inline.
64
64
 
65
- subworkflow: Type["BaseWorkflow[WorkflowInputsType, InnerStateType]"] - The Subworkflow to execute
65
+ subworkflow: Type["BaseWorkflow[InputsType, InnerStateType]"] - The Subworkflow to execute
66
66
  subworkflow_inputs: ClassVar[EntityInputsInterface] = {}
67
67
  """
68
68
 
69
- subworkflow: Type["BaseWorkflow[WorkflowInputsType, InnerStateType]"]
69
+ subworkflow: Type["BaseWorkflow[InputsType, InnerStateType]"]
70
70
  subworkflow_inputs: ClassVar[Union[EntityInputsInterface, BaseInputs, Type[UNDEF]]] = UNDEF
71
71
 
72
72
  def run(self) -> Iterator[BaseOutput]:
@@ -109,7 +109,7 @@ class InlineSubworkflowNode(
109
109
  value=output_value,
110
110
  )
111
111
 
112
- def _compile_subworkflow_inputs(self) -> WorkflowInputsType:
112
+ def _compile_subworkflow_inputs(self) -> InputsType:
113
113
  inputs_class = self.subworkflow.get_inputs_class()
114
114
  if self.subworkflow_inputs is UNDEF:
115
115
  inputs_dict = {}
@@ -65,7 +65,7 @@ from vellum.workflows.ports.port import Port
65
65
  from vellum.workflows.references import ExternalInputReference, OutputReference
66
66
  from vellum.workflows.state.base import BaseState
67
67
  from vellum.workflows.types.cycle_map import CycleMap
68
- from vellum.workflows.types.generics import OutputsType, StateType, WorkflowInputsType
68
+ from vellum.workflows.types.generics import InputsType, OutputsType, StateType
69
69
 
70
70
  if TYPE_CHECKING:
71
71
  from vellum.workflows import BaseWorkflow
@@ -82,8 +82,8 @@ class WorkflowRunner(Generic[StateType]):
82
82
 
83
83
  def __init__(
84
84
  self,
85
- workflow: "BaseWorkflow[WorkflowInputsType, StateType]",
86
- inputs: Optional[WorkflowInputsType] = None,
85
+ workflow: "BaseWorkflow[InputsType, StateType]",
86
+ inputs: Optional[InputsType] = None,
87
87
  state: Optional[StateType] = None,
88
88
  entrypoint_nodes: Optional[RunFromNodeArg] = None,
89
89
  external_inputs: Optional[ExternalInputsArg] = None,
@@ -10,5 +10,5 @@ if TYPE_CHECKING:
10
10
  NodeType = TypeVar("NodeType", bound="BaseNode")
11
11
  StateType = TypeVar("StateType", bound="BaseState")
12
12
  WorkflowType = TypeVar("WorkflowType", bound="BaseWorkflow")
13
- WorkflowInputsType = TypeVar("WorkflowInputsType", bound="BaseInputs")
13
+ InputsType = TypeVar("InputsType", bound="BaseInputs")
14
14
  OutputsType = TypeVar("OutputsType", bound="BaseOutputs")
@@ -68,7 +68,7 @@ from vellum.workflows.runner.runner import ExternalInputsArg, RunFromNodeArg
68
68
  from vellum.workflows.state.base import BaseState, StateMeta
69
69
  from vellum.workflows.state.context import WorkflowContext
70
70
  from vellum.workflows.state.store import Store
71
- from vellum.workflows.types.generics import StateType, WorkflowInputsType
71
+ from vellum.workflows.types.generics import InputsType, StateType
72
72
  from vellum.workflows.types.utils import get_original_base
73
73
  from vellum.workflows.utils.uuids import uuid4_from_hash
74
74
  from vellum.workflows.workflows.event_filters import workflow_event_filter
@@ -88,7 +88,7 @@ class _BaseWorkflowMeta(type):
88
88
  GraphAttribute = Union[Type[BaseNode], Graph, Set[Type[BaseNode]], Set[Graph]]
89
89
 
90
90
 
91
- class BaseWorkflow(Generic[WorkflowInputsType, StateType], metaclass=_BaseWorkflowMeta):
91
+ class BaseWorkflow(Generic[InputsType, StateType], metaclass=_BaseWorkflowMeta):
92
92
  __id__: UUID = uuid4_from_hash(__qualname__)
93
93
  graph: ClassVar[GraphAttribute]
94
94
  emitters: List[BaseWorkflowEmitter]
@@ -99,7 +99,7 @@ class BaseWorkflow(Generic[WorkflowInputsType, StateType], metaclass=_BaseWorkfl
99
99
 
100
100
  WorkflowEvent = Union[ # type: ignore
101
101
  GenericWorkflowEvent,
102
- WorkflowExecutionInitiatedEvent[WorkflowInputsType], # type: ignore[valid-type]
102
+ WorkflowExecutionInitiatedEvent[InputsType], # type: ignore[valid-type]
103
103
  WorkflowExecutionFulfilledEvent[Outputs],
104
104
  WorkflowExecutionSnapshottedEvent[StateType], # type: ignore[valid-type]
105
105
  ]
@@ -181,7 +181,7 @@ class BaseWorkflow(Generic[WorkflowInputsType, StateType], metaclass=_BaseWorkfl
181
181
 
182
182
  def run(
183
183
  self,
184
- inputs: Optional[WorkflowInputsType] = None,
184
+ inputs: Optional[InputsType] = None,
185
185
  *,
186
186
  state: Optional[StateType] = None,
187
187
  entrypoint_nodes: Optional[RunFromNodeArg] = None,
@@ -198,7 +198,7 @@ class BaseWorkflow(Generic[WorkflowInputsType, StateType], metaclass=_BaseWorkfl
198
198
 
199
199
  Parameters
200
200
  ----------
201
- inputs: Optional[WorkflowInputsType] = None
201
+ inputs: Optional[InputsType] = None
202
202
  The Inputs instance used to initiate the Workflow Execution.
203
203
 
204
204
  state: Optional[StateType] = None
@@ -288,7 +288,7 @@ class BaseWorkflow(Generic[WorkflowInputsType, StateType], metaclass=_BaseWorkfl
288
288
 
289
289
  def stream(
290
290
  self,
291
- inputs: Optional[WorkflowInputsType] = None,
291
+ inputs: Optional[InputsType] = None,
292
292
  *,
293
293
  event_filter: Optional[Callable[[Type["BaseWorkflow"], WorkflowEvent], bool]] = None,
294
294
  state: Optional[StateType] = None,
@@ -307,7 +307,7 @@ class BaseWorkflow(Generic[WorkflowInputsType, StateType], metaclass=_BaseWorkfl
307
307
  A filter that can be used to filter events based on the Workflow Class and the event itself. If the method
308
308
  returns `False`, the event will not be yielded.
309
309
 
310
- inputs: Optional[WorkflowInputsType] = None
310
+ inputs: Optional[InputsType] = None
311
311
  The Inputs instance used to initiate the Workflow Execution.
312
312
 
313
313
  state: Optional[StateType] = None
@@ -359,7 +359,7 @@ class BaseWorkflow(Generic[WorkflowInputsType, StateType], metaclass=_BaseWorkfl
359
359
  @lru_cache
360
360
  def _get_parameterized_classes(
361
361
  cls,
362
- ) -> Tuple[Type[WorkflowInputsType], Type[StateType]]:
362
+ ) -> Tuple[Type[InputsType], Type[StateType]]:
363
363
  original_base = get_original_base(cls)
364
364
 
365
365
  inputs_type, state_type = get_args(original_base)
@@ -378,17 +378,17 @@ class BaseWorkflow(Generic[WorkflowInputsType, StateType], metaclass=_BaseWorkfl
378
378
  return (inputs_type, state_type)
379
379
 
380
380
  @classmethod
381
- def get_inputs_class(cls) -> Type[WorkflowInputsType]:
381
+ def get_inputs_class(cls) -> Type[InputsType]:
382
382
  return cls._get_parameterized_classes()[0]
383
383
 
384
384
  @classmethod
385
385
  def get_state_class(cls) -> Type[StateType]:
386
386
  return cls._get_parameterized_classes()[1]
387
387
 
388
- def get_default_inputs(self) -> WorkflowInputsType:
388
+ def get_default_inputs(self) -> InputsType:
389
389
  return self.get_inputs_class()()
390
390
 
391
- def get_default_state(self, workflow_inputs: Optional[WorkflowInputsType] = None) -> StateType:
391
+ def get_default_state(self, workflow_inputs: Optional[InputsType] = None) -> StateType:
392
392
  return self.get_state_class()(
393
393
  meta=StateMeta(
394
394
  parent=self._parent_state,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vellum-ai
3
- Version: 0.13.20
3
+ Version: 0.13.21
4
4
  Summary:
5
5
  License: MIT
6
6
  Requires-Python: >=3.9,<4.0
@@ -79,12 +79,13 @@ vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_ser
79
79
  vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py,sha256=xmKyOKqGRhWUXXbTbCAXX40qINcvK7mjpEfXz0Ny21s,7404
80
80
  vellum_ee/workflows/display/types.py,sha256=jWTpfQv3baEWjbP12duc3MBz3TK03Ja1UI5458PVQVY,4211
81
81
  vellum_ee/workflows/display/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
82
- vellum_ee/workflows/display/utils/vellum.py,sha256=I0a8zFg4YIiT1ZTI27sEHuT9AM9PzktqBmrQ-Mqs3Ww,7328
82
+ vellum_ee/workflows/display/utils/vellum.py,sha256=IGHobHz0QG8TWdJNxlQ81khCmJv7piLjE64l4zc33kI,7743
83
83
  vellum_ee/workflows/display/vellum.py,sha256=-95xvit30nyP6Md29nHkfIrnFButZyCg8wz76oUHD0M,8105
84
84
  vellum_ee/workflows/display/workflows/__init__.py,sha256=kapXsC67VJcgSuiBMa86FdePG5A9kMB5Pi4Uy1O2ob4,207
85
85
  vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256=x4C621UTH_SZLJYmVBiC1q-D-wadJlTiSGlKAI6CUbA,14082
86
86
  vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py,sha256=kp0u8LN_2IwshLrhMImhpZx1hRyAcD5gXY-kDuuaGMQ,1269
87
- vellum_ee/workflows/display/workflows/vellum_workflow_display.py,sha256=h8lCnuBfI5muxDi8i9u6tlgJIGEoJnSPc7jbJmECygg,16836
87
+ vellum_ee/workflows/display/workflows/tests/test_workflow_display.py,sha256=yl1ytpl9_lijOGeDPWSypWYRJ7aOEVA7NgUg81jTuCs,2229
88
+ vellum_ee/workflows/display/workflows/vellum_workflow_display.py,sha256=IiHfMglir81cwPFYnwvgynp79cgzFyYVkMJAABIi3BQ,17035
88
89
  vellum_ee/workflows/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
89
90
  vellum_ee/workflows/server/virtual_file_loader.py,sha256=X_DdNK7MfyOjKWekk6YQpOSCT6klKcdjT6nVJcBH1sM,1481
90
91
  vellum_ee/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -113,7 +114,7 @@ vellum/client/README.md,sha256=JkCJjmMZl4jrPj46pkmL9dpK4gSzQQmP5I7z4aME4LY,4749
113
114
  vellum/client/__init__.py,sha256=8nZt88C9SVwWanjLbIQMU3rzb32h5UZfFMBx3VPHB50,111887
114
115
  vellum/client/core/__init__.py,sha256=SQ85PF84B9MuKnBwHNHWemSGuy-g_515gFYNFhvEE0I,1438
115
116
  vellum/client/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
116
- vellum/client/core/client_wrapper.py,sha256=z1NZHCGeJAfuF3tZN-NenmROQ_g76uDXyCzW3tI-Hbs,1869
117
+ vellum/client/core/client_wrapper.py,sha256=5SwzGdamiAC-bG69Fab06ulKRPF_5B1kp_GF6a4fr3g,1869
117
118
  vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
118
119
  vellum/client/core/file.py,sha256=X9IbmkZmB2bB_DpmZAO3crWdXagOakAyn6UCOCImCPg,2322
119
120
  vellum/client/core/http_client.py,sha256=R0pQpCppnEtxccGvXl4uJ76s7ro_65Fo_erlNNLp_AI,19228
@@ -1269,7 +1270,7 @@ vellum/workflows/events/node.py,sha256=uHT6If0esgZ3nLjrjmUPTKf3qbjGhoV_x5YKpjDBD
1269
1270
  vellum/workflows/events/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1270
1271
  vellum/workflows/events/tests/test_event.py,sha256=9rbp92dQXpGFad-LjE2nYU17neKkiHxQz9X8RsoCWs4,13718
1271
1272
  vellum/workflows/events/types.py,sha256=cjRE8WL8tYCFradd9NOGl_H0mN3LiWWnA1uHmyT2Q0Q,3412
1272
- vellum/workflows/events/workflow.py,sha256=l5tXes0sg7iWaA1ZUE5dtAqNnGQ8iy6trVbOU9meu7U,5240
1273
+ vellum/workflows/events/workflow.py,sha256=lveoWXtVRLjdO_nu0z6VlKeTqlGimogamiFR-jYihlE,5184
1273
1274
  vellum/workflows/exceptions.py,sha256=l-FLGvXywxg6ivolCts71b8pcsYAWoB1cmUR4Jx7N8g,614
1274
1275
  vellum/workflows/expressions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1275
1276
  vellum/workflows/expressions/accessor.py,sha256=daIkEudAdyiqCOzO9x_3cy-Y9ilYgNWSEeqcFelkjI0,1743
@@ -1301,15 +1302,15 @@ vellum/workflows/expressions/not_between.py,sha256=H2huRR95D9Qb7lCHmK7BcK-Ug-E1g
1301
1302
  vellum/workflows/expressions/not_in.py,sha256=OQkN5G1E6VoTDpoLvx7X3GbohLlqEAYHV0rVVUV7ow4,1049
1302
1303
  vellum/workflows/expressions/or_.py,sha256=s-8YdMSSCDS2yijR38kguwok3iqmDMMgDYKV93b4O4s,914
1303
1304
  vellum/workflows/graph/__init__.py,sha256=3sHlay5d_-uD7j3QJXiGl0WHFZZ_QScRvgyDhN2GhHY,74
1304
- vellum/workflows/graph/graph.py,sha256=rmPPs2gtQhaYIuZKETdWrdacgwQRvT6soj12UOl1Tm0,5316
1305
+ vellum/workflows/graph/graph.py,sha256=GGR8cGpSuNWPIiTWNWsj6l70upb5nIxAyFcn7VdaJIs,5506
1305
1306
  vellum/workflows/graph/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1306
- vellum/workflows/graph/tests/test_graph.py,sha256=PQI1lO2IY-izBSbkwxjKR5a1z-aN-ieHV_p0m-g5eAM,11256
1307
+ vellum/workflows/graph/tests/test_graph.py,sha256=q0wxLvPPxc-6en4a_XuAZwVfLURMd9Ikvoreq4bpJ9s,11839
1307
1308
  vellum/workflows/inputs/__init__.py,sha256=AbFEteIYEvCb14fM3EK7bhM-40-6s494rSlIhQ4Dsss,62
1308
1309
  vellum/workflows/inputs/base.py,sha256=1kMgr0WqCYdWUqgFvgSoAMw2067FAlgwhGXLgbIOrLY,2391
1309
1310
  vellum/workflows/logging.py,sha256=_a217XogktV4Ncz6xKFz7WfYmZAzkfVRVuC0rWob8ls,437
1310
1311
  vellum/workflows/nodes/__init__.py,sha256=aVdQVv7Y3Ro3JlqXGpxwaU2zrI06plDHD2aumH5WUIs,1157
1311
1312
  vellum/workflows/nodes/bases/__init__.py,sha256=cniHuz_RXdJ4TQgD8CBzoiKDiPxg62ErdVpCbWICX64,58
1312
- vellum/workflows/nodes/bases/base.py,sha256=qzuf8InU_DZtat-ZsROEHLwmd08pVsYxeoweU5PWQ74,14162
1313
+ vellum/workflows/nodes/bases/base.py,sha256=v6Y38xRTTKQxfvDpnx7X37EQN6Mrxu2vKtMDQiR2g8A,14186
1313
1314
  vellum/workflows/nodes/bases/base_adornment_node.py,sha256=eFTgsPCYb3eyGS0-kw7C6crFnwFx437R5wh9-8bWYts,2905
1314
1315
  vellum/workflows/nodes/bases/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1315
1316
  vellum/workflows/nodes/bases/tests/test_base_node.py,sha256=51CueFVty9XYASC0rKr1cXWejho5WElmhfhp6cCONy0,3811
@@ -1317,7 +1318,7 @@ vellum/workflows/nodes/core/__init__.py,sha256=5zDMCmyt1v0HTJzlUBwq3U9L825yZGZhT
1317
1318
  vellum/workflows/nodes/core/error_node/__init__.py,sha256=g7RRnlHhqu4qByfLjBwCunmgGA8dI5gNsjS3h6TwlSI,60
1318
1319
  vellum/workflows/nodes/core/error_node/node.py,sha256=MFHU5vITYSK-L9CuMZ49In2ZeNLWnhZD0f8r5dWvb5Y,1270
1319
1320
  vellum/workflows/nodes/core/inline_subworkflow_node/__init__.py,sha256=nKNEH1QTl-1PcvmYoqSWEl0-t6gAur8GLTXHzklRQfM,84
1320
- vellum/workflows/nodes/core/inline_subworkflow_node/node.py,sha256=q8_s1uuoB6t_QutJ-wl7Nj3A_yQYWxpv7660kcBwcXA,5931
1321
+ vellum/workflows/nodes/core/inline_subworkflow_node/node.py,sha256=yOVuY-J2IHCdOwt9VriSZwBRngB9MlFzmAmehqXMqlo,5891
1321
1322
  vellum/workflows/nodes/core/inline_subworkflow_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1322
1323
  vellum/workflows/nodes/core/inline_subworkflow_node/tests/test_node.py,sha256=n0-821Ov9ZfRFX_lbzLy5o2rX8fEw2qoxz0aFWCOxVg,1547
1323
1324
  vellum/workflows/nodes/core/map_node/__init__.py,sha256=MXpZYmGfhsMJHqqlpd64WiJRtbAtAMQz-_3fCU_cLV0,56
@@ -1411,7 +1412,7 @@ vellum/workflows/references/workflow_input.py,sha256=86IuhlBz-9cGxeUzizyjdp482aj
1411
1412
  vellum/workflows/resolvers/__init__.py,sha256=eH6hTvZO4IciDaf_cf7aM2vs-DkBDyJPycOQevJxQnI,82
1412
1413
  vellum/workflows/resolvers/base.py,sha256=WHra9LRtlTuB1jmuNqkfVE2JUgB61Cyntn8f0b0WZg4,411
1413
1414
  vellum/workflows/runner/__init__.py,sha256=i1iG5sAhtpdsrlvwgH6B-m49JsINkiWyPWs8vyT-bqM,72
1414
- vellum/workflows/runner/runner.py,sha256=LvP1UwLmwV1nCZYYrsiwtCzay73voMp1TDRVVBrlMj8,29196
1415
+ vellum/workflows/runner/runner.py,sha256=vGd5yfx4udwvGHkbFElDtsre__3JD8zIqhx6ZreRwN4,29172
1415
1416
  vellum/workflows/sandbox.py,sha256=GVJzVjMuYzOBnSrboB0_6MMRZWBluAyQ2o7syeaeBd0,2235
1416
1417
  vellum/workflows/state/__init__.py,sha256=yUUdR-_Vl7UiixNDYQZ-GEM_kJI9dnOia75TtuNEsnE,60
1417
1418
  vellum/workflows/state/base.py,sha256=IIl76sJtn0GfbFWBqMnpGuvtZyVyQMEXv0QKDfLy8Wg,14763
@@ -1425,7 +1426,7 @@ vellum/workflows/tests/test_sandbox.py,sha256=JKwaluI-lODQo7Ek9sjDstjL_WTdSqUlVi
1425
1426
  vellum/workflows/types/__init__.py,sha256=KxUTMBGzuRCfiMqzzsykOeVvrrkaZmTTo1a7SLu8gRM,68
1426
1427
  vellum/workflows/types/core.py,sha256=kMQremh_I8egXpiKmtMQbB6e3OczAWiRnnTq5V6xlD0,928
1427
1428
  vellum/workflows/types/cycle_map.py,sha256=-ZMQsKzZBpCi0bchJrkuN_dtCFuz9uFABy7Fq2PI58E,928
1428
- vellum/workflows/types/generics.py,sha256=ZkfoRhWs042i5IjA99v2wIhmh1u-Wieo3LzosgGWJVk,600
1429
+ vellum/workflows/types/generics.py,sha256=9HzFvtcF8qpn1wcsly7er250MMwdS9r-BjSVco9UBj4,584
1429
1430
  vellum/workflows/types/stack.py,sha256=RDSGLkcV612ge8UuAH9TZiEGXxJt0Av2-H5rfzrTVVI,1014
1430
1431
  vellum/workflows/types/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
1431
1432
  vellum/workflows/types/tests/test_utils.py,sha256=y2bj4O8-ykPRRRocdD98NdnQz6ydSCoMBp6rECPPqE8,2536
@@ -1442,10 +1443,10 @@ vellum/workflows/utils/uuids.py,sha256=DFzPv9RCvsKhvdTEIQyfSek2A31D6S_QcmeLPbgrg
1442
1443
  vellum/workflows/utils/vellum_variables.py,sha256=g5xHYB8etfHE32ek19nP6Anf8NyjhmUtOwO2KmQ5xZU,3111
1443
1444
  vellum/workflows/vellum_client.py,sha256=ODrq_TSl-drX2aezXegf7pizpWDVJuTXH-j6528t75s,683
1444
1445
  vellum/workflows/workflows/__init__.py,sha256=KY45TqvavCCvXIkyCFMEc0dc6jTMOUci93U2DUrlZYc,66
1445
- vellum/workflows/workflows/base.py,sha256=k0kUWWko4fHyCqLSU_1cBK_pXZpl9MXekWiG-bdOAo0,18353
1446
+ vellum/workflows/workflows/base.py,sha256=kL4lxTdhaupw58sqzCutI5K8tDSfk2gHXDddCrg6FGA,18265
1446
1447
  vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnadGsrSZGa7t7LpJA,2008
1447
- vellum_ai-0.13.20.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1448
- vellum_ai-0.13.20.dist-info/METADATA,sha256=TbxOMd3MKv1utYPQA2QHrmmbGBD5eSJaj1QPRLHkQsE,5335
1449
- vellum_ai-0.13.20.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1450
- vellum_ai-0.13.20.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1451
- vellum_ai-0.13.20.dist-info/RECORD,,
1448
+ vellum_ai-0.13.21.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
1449
+ vellum_ai-0.13.21.dist-info/METADATA,sha256=DVUX-LtxUw5KFTUz0NzF92v-sCkAczyHJ9zDeDfD3og,5335
1450
+ vellum_ai-0.13.21.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
1451
+ vellum_ai-0.13.21.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
1452
+ vellum_ai-0.13.21.dist-info/RECORD,,
@@ -28,6 +28,7 @@ from vellum.workflows.expressions.less_than_or_equal_to import LessThanOrEqualTo
28
28
  from vellum.workflows.expressions.not_between import NotBetweenExpression
29
29
  from vellum.workflows.expressions.not_in import NotInExpression
30
30
  from vellum.workflows.expressions.or_ import OrExpression
31
+ from vellum.workflows.nodes.bases.base import BaseNode
31
32
  from vellum.workflows.nodes.displayable.bases.utils import primitive_to_vellum_value
32
33
  from vellum.workflows.references import OutputReference, WorkflowInputReference
33
34
  from vellum.workflows.references.execution_count import ExecutionCountReference
@@ -76,6 +77,12 @@ def create_node_input_value_pointer_rule(
76
77
  value: Any, display_context: "WorkflowDisplayContext"
77
78
  ) -> NodeInputValuePointerRule:
78
79
  if isinstance(value, OutputReference):
80
+ if value not in display_context.global_node_output_displays:
81
+ if issubclass(value.outputs_class, BaseNode.Outputs):
82
+ raise ValueError(f"Reference to node '{value.outputs_class._node_class.__name__}' not found in graph.")
83
+
84
+ raise ValueError(f"Reference to outputs '{value.outputs_class.__qualname__}' is invalid.")
85
+
79
86
  upstream_node, output_display = display_context.global_node_output_displays[value]
80
87
  upstream_node_display = display_context.global_node_displays[upstream_node]
81
88
  return NodeOutputPointer(
@@ -0,0 +1,65 @@
1
+ import pytest
2
+
3
+ from vellum.workflows.nodes.bases.base import BaseNode
4
+ from vellum.workflows.workflows.base import BaseWorkflow
5
+ from vellum_ee.workflows.display.workflows import VellumWorkflowDisplay
6
+ from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
7
+
8
+
9
+ def test_serialize_workflow__node_referenced_in_workflow_outputs_not_in_graph():
10
+ # GIVEN a couple of nodes
11
+ class InNode(BaseNode):
12
+ pass
13
+
14
+ class OutNode(BaseNode):
15
+ class Outputs(BaseNode.Outputs):
16
+ foo: str
17
+
18
+ # AND A workflow that references the OutNode in its outputs but only has the InNode in its graph
19
+ class Workflow(BaseWorkflow):
20
+ graph = InNode
21
+
22
+ class Outputs(BaseWorkflow.Outputs):
23
+ final = OutNode.Outputs.foo
24
+
25
+ # WHEN we serialize it
26
+ workflow_display = get_workflow_display(
27
+ base_display_class=VellumWorkflowDisplay,
28
+ workflow_class=Workflow,
29
+ )
30
+
31
+ # THEN it should raise an error
32
+ with pytest.raises(ValueError) as exc_info:
33
+ workflow_display.serialize()
34
+
35
+ # AND the error message should be user friendly
36
+ assert str(exc_info.value) == "Failed to serialize output 'final': Reference to node 'OutNode' not found in graph."
37
+
38
+
39
+ def test_serialize_workflow__workflow_outputs_reference_non_node_outputs():
40
+ # GIVEN one Workflow
41
+ class FirstWorkflow(BaseWorkflow):
42
+ class Outputs(BaseWorkflow.Outputs):
43
+ foo = "bar"
44
+
45
+ # AND A workflow that references the Outputs of that Workflow
46
+ class Workflow(BaseWorkflow):
47
+ class Outputs(BaseWorkflow.Outputs):
48
+ final = FirstWorkflow.Outputs.foo
49
+
50
+ # WHEN we serialize it
51
+ workflow_display = get_workflow_display(
52
+ base_display_class=VellumWorkflowDisplay,
53
+ workflow_class=Workflow,
54
+ )
55
+
56
+ # THEN it should raise an error
57
+ with pytest.raises(ValueError) as exc_info:
58
+ workflow_display.serialize()
59
+
60
+ # AND the error message should be user friendly
61
+ assert (
62
+ str(exc_info.value)
63
+ == """Failed to serialize output 'final': Reference to outputs \
64
+ 'test_serialize_workflow__workflow_outputs_reference_non_node_outputs.<locals>.FirstWorkflow.Outputs' is invalid."""
65
+ )
@@ -129,13 +129,16 @@ class VellumWorkflowDisplay(
129
129
 
130
130
  if workflow_output.instance not in final_output_node_outputs:
131
131
  # Create a synthetic terminal node only if there is no terminal node for this output
132
- node_input = create_node_input(
133
- final_output_node_id,
134
- "node_input",
135
- # This is currently the wrapper node's output, but we want the wrapped node
136
- workflow_output.instance,
137
- self.display_context,
138
- )
132
+ try:
133
+ node_input = create_node_input(
134
+ final_output_node_id,
135
+ "node_input",
136
+ # This is currently the wrapper node's output, but we want the wrapped node
137
+ workflow_output.instance,
138
+ self.display_context,
139
+ )
140
+ except ValueError as e:
141
+ raise ValueError(f"Failed to serialize output '{workflow_output.name}': {str(e)}") from e
139
142
 
140
143
  source_node_display: Optional[BaseNodeDisplay]
141
144
  first_rule = node_input.value.rules[0]