vellum-ai 0.14.39__py3-none-any.whl → 0.14.41__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.
- vellum/client/core/client_wrapper.py +1 -1
- vellum/client/reference.md +138 -1
- vellum/client/resources/ad_hoc/client.py +311 -1
- vellum/client/resources/deployments/client.py +2 -2
- vellum/workflows/nodes/bases/tests/test_base_node.py +24 -0
- vellum/workflows/nodes/core/try_node/node.py +1 -2
- vellum/workflows/nodes/experimental/tool_calling_node/__init__.py +3 -0
- vellum/workflows/nodes/experimental/tool_calling_node/node.py +125 -0
- vellum/workflows/nodes/experimental/tool_calling_node/utils.py +128 -0
- vellum/workflows/nodes/utils.py +4 -2
- vellum/workflows/outputs/base.py +3 -2
- vellum/workflows/references/output.py +20 -0
- vellum/workflows/state/base.py +36 -14
- vellum/workflows/state/tests/test_state.py +5 -2
- vellum/workflows/types/stack.py +11 -0
- vellum/workflows/workflows/base.py +5 -0
- vellum/workflows/workflows/tests/test_base_workflow.py +96 -9
- {vellum_ai-0.14.39.dist-info → vellum_ai-0.14.41.dist-info}/METADATA +1 -1
- {vellum_ai-0.14.39.dist-info → vellum_ai-0.14.41.dist-info}/RECORD +84 -80
- vellum_cli/push.py +0 -2
- vellum_ee/workflows/display/base.py +14 -1
- vellum_ee/workflows/display/nodes/base_node_display.py +91 -19
- vellum_ee/workflows/display/nodes/get_node_display_class.py +9 -15
- vellum_ee/workflows/display/nodes/tests/test_base_node_display.py +54 -0
- vellum_ee/workflows/display/nodes/vellum/api_node.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/base_adornment_node.py +4 -4
- vellum_ee/workflows/display/nodes/vellum/code_execution_node.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/conditional_node.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/error_node.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/final_output_node.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/guardrail_node.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/inline_prompt_node.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/inline_subworkflow_node.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/merge_node.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/note_node.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py +2 -4
- vellum_ee/workflows/display/nodes/vellum/retry_node.py +1 -2
- vellum_ee/workflows/display/nodes/vellum/search_node.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/templating_node.py +2 -2
- vellum_ee/workflows/display/nodes/vellum/tests/test_code_execution_node.py +1 -2
- vellum_ee/workflows/display/nodes/vellum/tests/test_error_node.py +1 -2
- vellum_ee/workflows/display/nodes/vellum/tests/test_note_node.py +1 -2
- vellum_ee/workflows/display/nodes/vellum/tests/test_prompt_node.py +55 -3
- vellum_ee/workflows/display/nodes/vellum/tests/test_retry_node.py +1 -2
- vellum_ee/workflows/display/nodes/vellum/tests/test_templating_node.py +1 -2
- vellum_ee/workflows/display/nodes/vellum/tests/test_try_node.py +1 -2
- vellum_ee/workflows/display/nodes/vellum/tests/test_utils.py +4 -4
- vellum_ee/workflows/display/nodes/vellum/try_node.py +1 -2
- vellum_ee/workflows/display/nodes/vellum/utils.py +7 -1
- vellum_ee/workflows/display/tests/{test_vellum_workflow_display.py → test_base_workflow_display.py} +10 -22
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/conftest.py +4 -6
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +7 -16
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_attributes_serialization.py +2 -6
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py +1 -2
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +3 -10
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +4 -5
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_default_state_serialization.py +1 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py +1 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py +2 -5
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py +7 -5
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_prompt_node_serialization.py +1 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +1 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +1 -2
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +1 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py +1 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_serialization.py +7 -5
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py +1 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py +1 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py +1 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py +2 -5
- vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py +2 -7
- vellum_ee/workflows/display/types.py +5 -4
- vellum_ee/workflows/display/utils/exceptions.py +7 -0
- vellum_ee/workflows/display/utils/registry.py +37 -0
- vellum_ee/workflows/display/utils/vellum.py +2 -1
- vellum_ee/workflows/display/workflows/base_workflow_display.py +277 -47
- vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py +34 -21
- vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +58 -20
- vellum_ee/workflows/display/workflows/vellum_workflow_display.py +4 -257
- vellum_ee/workflows/tests/local_workflow/display/workflow.py +2 -2
- vellum_ee/workflows/display/nodes/base_node_vellum_display.py +0 -40
- {vellum_ai-0.14.39.dist-info → vellum_ai-0.14.41.dist-info}/LICENSE +0 -0
- {vellum_ai-0.14.39.dist-info → vellum_ai-0.14.41.dist-info}/WHEEL +0 -0
- {vellum_ai-0.14.39.dist-info → vellum_ai-0.14.41.dist-info}/entry_points.txt +0 -0
@@ -11,7 +11,6 @@ from vellum_ee.workflows.display.editor.types import NodeDisplayData, NodeDispla
|
|
11
11
|
from vellum_ee.workflows.display.nodes import BaseNodeDisplay
|
12
12
|
from vellum_ee.workflows.display.nodes.vellum.retry_node import BaseRetryNodeDisplay
|
13
13
|
from vellum_ee.workflows.display.nodes.vellum.try_node import BaseTryNodeDisplay
|
14
|
-
from vellum_ee.workflows.display.workflows import VellumWorkflowDisplay
|
15
14
|
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
16
15
|
|
17
16
|
|
@@ -32,10 +31,7 @@ def test_serialize_workflow__node_referenced_in_workflow_outputs_not_in_graph():
|
|
32
31
|
final = OutNode.Outputs.foo
|
33
32
|
|
34
33
|
# WHEN we serialize it
|
35
|
-
workflow_display = get_workflow_display(
|
36
|
-
base_display_class=VellumWorkflowDisplay,
|
37
|
-
workflow_class=Workflow,
|
38
|
-
)
|
34
|
+
workflow_display = get_workflow_display(workflow_class=Workflow)
|
39
35
|
|
40
36
|
# THEN it should raise an error
|
41
37
|
with pytest.raises(ValueError) as exc_info:
|
@@ -57,10 +53,7 @@ def test_serialize_workflow__workflow_outputs_reference_non_node_outputs():
|
|
57
53
|
final = FirstWorkflow.Outputs.foo
|
58
54
|
|
59
55
|
# WHEN we serialize it
|
60
|
-
workflow_display = get_workflow_display(
|
61
|
-
base_display_class=VellumWorkflowDisplay,
|
62
|
-
workflow_class=Workflow,
|
63
|
-
)
|
56
|
+
workflow_display = get_workflow_display(workflow_class=Workflow)
|
64
57
|
|
65
58
|
# THEN it should raise an error
|
66
59
|
with pytest.raises(ValueError) as exc_info:
|
@@ -91,10 +84,7 @@ def test_serialize_workflow__node_display_class_not_registered():
|
|
91
84
|
answer = StartNode.Outputs.result
|
92
85
|
|
93
86
|
# WHEN we serialize it
|
94
|
-
workflow_display = get_workflow_display(
|
95
|
-
base_display_class=VellumWorkflowDisplay,
|
96
|
-
workflow_class=MyWorkflow,
|
97
|
-
)
|
87
|
+
workflow_display = get_workflow_display(workflow_class=MyWorkflow)
|
98
88
|
data = workflow_display.serialize()
|
99
89
|
|
100
90
|
# THEN it should should succeed
|
@@ -111,7 +101,7 @@ def test_get_event_display_context__node_display_filled_without_base_display():
|
|
111
101
|
graph = StartNode
|
112
102
|
|
113
103
|
# WHEN we gather the event display context
|
114
|
-
display_context =
|
104
|
+
display_context = get_workflow_display(workflow_class=MyWorkflow).get_event_display_context()
|
115
105
|
|
116
106
|
# THEN the node display should be included
|
117
107
|
assert StartNode.__id__ in display_context.node_displays
|
@@ -134,7 +124,7 @@ def test_get_event_display_context__node_display_filled_without_output_display()
|
|
134
124
|
pass
|
135
125
|
|
136
126
|
# WHEN we gather the event display context
|
137
|
-
display_context =
|
127
|
+
display_context = get_workflow_display(workflow_class=MyWorkflow).get_event_display_context()
|
138
128
|
|
139
129
|
# THEN the node display should be included
|
140
130
|
assert StartNode.__id__ in display_context.node_displays
|
@@ -160,7 +150,7 @@ def test_get_event_display_context__node_display_to_include_subworkflow_display(
|
|
160
150
|
graph = SubworkflowNode
|
161
151
|
|
162
152
|
# WHEN we gather the event display context
|
163
|
-
display_context =
|
153
|
+
display_context = get_workflow_display(workflow_class=MyWorkflow).get_event_display_context()
|
164
154
|
|
165
155
|
# THEN the subworkflow display should be included
|
166
156
|
assert SubworkflowNode.__id__ in display_context.node_displays
|
@@ -201,7 +191,7 @@ def test_get_event_display_context__node_display_for_adornment_nodes(
|
|
201
191
|
node_id = inner_node_id
|
202
192
|
|
203
193
|
# WHEN we gather the event display context
|
204
|
-
display_context =
|
194
|
+
display_context = get_workflow_display(workflow_class=MyWorkflow).get_event_display_context()
|
205
195
|
|
206
196
|
# THEN the subworkflow display should be included
|
207
197
|
assert adornment_node_id in display_context.node_displays
|
@@ -228,7 +218,7 @@ def test_get_event_display_context__templating_node_input_display():
|
|
228
218
|
graph = DataNode >> MyNode
|
229
219
|
|
230
220
|
# WHEN we gather the event display context
|
231
|
-
display_context =
|
221
|
+
display_context = get_workflow_display(workflow_class=MyWorkflow).get_event_display_context()
|
232
222
|
|
233
223
|
# THEN the subworkflow display should be included
|
234
224
|
assert MyNode.__id__ in display_context.node_displays
|
@@ -259,7 +249,7 @@ def test_get_event_display_context__node_display_for_mutiple_adornments():
|
|
259
249
|
node_id = innermost_node_id
|
260
250
|
|
261
251
|
# WHEN we gather the event display context
|
262
|
-
display_context =
|
252
|
+
display_context = get_workflow_display(workflow_class=MyWorkflow).get_event_display_context()
|
263
253
|
|
264
254
|
# THEN the subworkflow display should be included
|
265
255
|
assert node_id in display_context.node_displays
|
@@ -285,7 +275,55 @@ def test_get_event_display_context__workflow_output_display_with_none():
|
|
285
275
|
bar = "baz"
|
286
276
|
|
287
277
|
# WHEN we gather the event display context
|
288
|
-
display_context =
|
278
|
+
display_context = get_workflow_display(workflow_class=MyWorkflow).get_event_display_context()
|
289
279
|
|
290
280
|
# THEN the workflow output display should be included
|
291
281
|
assert display_context.workflow_outputs.keys() == {"foo", "bar"}
|
282
|
+
|
283
|
+
|
284
|
+
def test_serialize_workflow__inherited_node_display_class_not_registered():
|
285
|
+
# GIVEN a node meant to be used as a base
|
286
|
+
class StartNode(BaseNode):
|
287
|
+
class Outputs(BaseNode.Outputs):
|
288
|
+
result: str
|
289
|
+
|
290
|
+
# AND a node that inherits from it
|
291
|
+
class InheritedNode(StartNode):
|
292
|
+
foo: str
|
293
|
+
|
294
|
+
# AND a workflow that uses the inherited node
|
295
|
+
class MyWorkflow(BaseWorkflow):
|
296
|
+
graph = InheritedNode
|
297
|
+
|
298
|
+
class Outputs(BaseWorkflow.Outputs):
|
299
|
+
answer = InheritedNode.Outputs.result
|
300
|
+
|
301
|
+
# WHEN we serialize it
|
302
|
+
workflow_display = get_workflow_display(workflow_class=MyWorkflow)
|
303
|
+
data = workflow_display.serialize()
|
304
|
+
|
305
|
+
# THEN it should should succeed
|
306
|
+
assert data is not None
|
307
|
+
|
308
|
+
|
309
|
+
def test_serialize_workflow__inherited_workflow_display_class_not_registered():
|
310
|
+
# GIVEN a node
|
311
|
+
class StartNode(BaseNode):
|
312
|
+
class Outputs(BaseNode.Outputs):
|
313
|
+
result: str
|
314
|
+
|
315
|
+
# AND a workflow that uses the node
|
316
|
+
class MyWorkflow(BaseWorkflow):
|
317
|
+
graph = StartNode
|
318
|
+
|
319
|
+
# AND a workflow that inherits from it
|
320
|
+
class InheritedWorkflow(MyWorkflow):
|
321
|
+
class Outputs(MyWorkflow.Outputs):
|
322
|
+
answer = StartNode.Outputs.result
|
323
|
+
|
324
|
+
# WHEN we serialize it
|
325
|
+
workflow_display = get_workflow_display(workflow_class=InheritedWorkflow)
|
326
|
+
data = workflow_display.serialize()
|
327
|
+
|
328
|
+
# THEN it should should succeed
|
329
|
+
assert data is not None
|
@@ -1,262 +1,9 @@
|
|
1
|
-
import
|
2
|
-
from uuid import UUID
|
3
|
-
from typing import Optional, cast
|
1
|
+
from typing import Generic
|
4
2
|
|
5
|
-
from vellum.workflows.constants import undefined
|
6
|
-
from vellum.workflows.nodes.displayable.bases.utils import primitive_to_vellum_value
|
7
|
-
from vellum.workflows.nodes.displayable.final_output_node import FinalOutputNode
|
8
|
-
from vellum.workflows.nodes.utils import get_unadorned_node, get_unadorned_port
|
9
|
-
from vellum.workflows.references.output import OutputReference
|
10
|
-
from vellum.workflows.types.core import JsonArray, JsonObject
|
11
3
|
from vellum.workflows.types.generics import WorkflowType
|
12
|
-
from vellum.workflows.utils.uuids import uuid4_from_hash
|
13
|
-
from vellum_ee.workflows.display.editor.types import NodeDisplayData
|
14
|
-
from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
|
15
|
-
from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
|
16
|
-
from vellum_ee.workflows.display.nodes.vellum.utils import create_node_input
|
17
|
-
from vellum_ee.workflows.display.utils.vellum import infer_vellum_variable_type
|
18
4
|
from vellum_ee.workflows.display.workflows.base_workflow_display import BaseWorkflowDisplay
|
19
5
|
|
20
|
-
logger = logging.getLogger(__name__)
|
21
6
|
|
22
|
-
|
23
|
-
class VellumWorkflowDisplay(BaseWorkflowDisplay[WorkflowType]):
|
24
|
-
|
25
|
-
|
26
|
-
def serialize(self) -> JsonObject:
|
27
|
-
input_variables: JsonArray = []
|
28
|
-
for workflow_input_reference, workflow_input_display in self.display_context.workflow_input_displays.items():
|
29
|
-
default = (
|
30
|
-
primitive_to_vellum_value(workflow_input_reference.instance)
|
31
|
-
if workflow_input_reference.instance
|
32
|
-
else None
|
33
|
-
)
|
34
|
-
input_variables.append(
|
35
|
-
{
|
36
|
-
"id": str(workflow_input_display.id),
|
37
|
-
"key": workflow_input_display.name or workflow_input_reference.name,
|
38
|
-
"type": infer_vellum_variable_type(workflow_input_reference),
|
39
|
-
"default": default.dict() if default else None,
|
40
|
-
"required": workflow_input_reference.instance is undefined,
|
41
|
-
"extensions": {"color": workflow_input_display.color},
|
42
|
-
}
|
43
|
-
)
|
44
|
-
|
45
|
-
state_variables: JsonArray = []
|
46
|
-
for state_value_reference, state_value_display in self.display_context.state_value_displays.items():
|
47
|
-
default = (
|
48
|
-
primitive_to_vellum_value(state_value_reference.instance) if state_value_reference.instance else None
|
49
|
-
)
|
50
|
-
state_variables.append(
|
51
|
-
{
|
52
|
-
"id": str(state_value_display.id),
|
53
|
-
"key": state_value_display.name or state_value_reference.name,
|
54
|
-
"type": infer_vellum_variable_type(state_value_reference),
|
55
|
-
"default": default.dict() if default else None,
|
56
|
-
"required": state_value_reference.instance is undefined,
|
57
|
-
"extensions": {"color": state_value_display.color},
|
58
|
-
}
|
59
|
-
)
|
60
|
-
|
61
|
-
nodes: JsonArray = []
|
62
|
-
edges: JsonArray = []
|
63
|
-
|
64
|
-
# Add a single synthetic node for the workflow entrypoint
|
65
|
-
entrypoint_node_id = self.display_context.workflow_display.entrypoint_node_id
|
66
|
-
entrypoint_node_source_handle_id = self.display_context.workflow_display.entrypoint_node_source_handle_id
|
67
|
-
nodes.append(
|
68
|
-
{
|
69
|
-
"id": str(entrypoint_node_id),
|
70
|
-
"type": "ENTRYPOINT",
|
71
|
-
"inputs": [],
|
72
|
-
"data": {
|
73
|
-
"label": "Entrypoint Node",
|
74
|
-
"source_handle_id": str(entrypoint_node_source_handle_id),
|
75
|
-
},
|
76
|
-
"display_data": self.display_context.workflow_display.entrypoint_node_display.dict(),
|
77
|
-
"base": None,
|
78
|
-
"definition": None,
|
79
|
-
},
|
80
|
-
)
|
81
|
-
|
82
|
-
# Add all the nodes in the workflow
|
83
|
-
for node in self._workflow.get_nodes():
|
84
|
-
node_display = self.display_context.node_displays[node]
|
85
|
-
|
86
|
-
try:
|
87
|
-
serialized_node = node_display.serialize(self.display_context)
|
88
|
-
except NotImplementedError as e:
|
89
|
-
self.add_error(e)
|
90
|
-
continue
|
91
|
-
|
92
|
-
nodes.append(serialized_node)
|
93
|
-
|
94
|
-
# Add all unused nodes in the workflow
|
95
|
-
for node in self._workflow.get_unused_nodes():
|
96
|
-
node_display = self.display_context.node_displays[node]
|
97
|
-
|
98
|
-
try:
|
99
|
-
serialized_node = node_display.serialize(self.display_context)
|
100
|
-
except NotImplementedError as e:
|
101
|
-
self.add_error(e)
|
102
|
-
continue
|
103
|
-
|
104
|
-
nodes.append(serialized_node)
|
105
|
-
|
106
|
-
synthetic_output_edges: JsonArray = []
|
107
|
-
output_variables: JsonArray = []
|
108
|
-
final_output_nodes = [
|
109
|
-
node for node in self.display_context.node_displays.keys() if issubclass(node, FinalOutputNode)
|
110
|
-
]
|
111
|
-
final_output_node_outputs = {node.Outputs.value for node in final_output_nodes}
|
112
|
-
unreferenced_final_output_node_outputs = final_output_node_outputs.copy()
|
113
|
-
final_output_node_base: JsonObject = {
|
114
|
-
"name": FinalOutputNode.__name__,
|
115
|
-
"module": cast(JsonArray, FinalOutputNode.__module__.split(".")),
|
116
|
-
}
|
117
|
-
|
118
|
-
# Add a synthetic Terminal Node and track the Workflow's output variables for each Workflow output
|
119
|
-
for workflow_output, workflow_output_display in self.display_context.workflow_output_displays.items():
|
120
|
-
final_output_node_id = uuid4_from_hash(f"{self.workflow_id}|node_id|{workflow_output.name}")
|
121
|
-
inferred_type = infer_vellum_variable_type(workflow_output)
|
122
|
-
|
123
|
-
# Remove the terminal node output from the unreferenced set
|
124
|
-
unreferenced_final_output_node_outputs.discard(cast(OutputReference, workflow_output.instance))
|
125
|
-
|
126
|
-
if workflow_output.instance not in final_output_node_outputs:
|
127
|
-
# Create a synthetic terminal node only if there is no terminal node for this output
|
128
|
-
try:
|
129
|
-
node_input = create_node_input(
|
130
|
-
final_output_node_id,
|
131
|
-
"node_input",
|
132
|
-
# This is currently the wrapper node's output, but we want the wrapped node
|
133
|
-
workflow_output.instance,
|
134
|
-
self.display_context,
|
135
|
-
)
|
136
|
-
except ValueError as e:
|
137
|
-
raise ValueError(f"Failed to serialize output '{workflow_output.name}': {str(e)}") from e
|
138
|
-
|
139
|
-
source_node_display: Optional[BaseNodeDisplay]
|
140
|
-
first_rule = node_input.value.rules[0]
|
141
|
-
if first_rule.type == "NODE_OUTPUT":
|
142
|
-
source_node_id = UUID(first_rule.data.node_id)
|
143
|
-
try:
|
144
|
-
source_node_display = [
|
145
|
-
node_display
|
146
|
-
for node_display in self.display_context.node_displays.values()
|
147
|
-
if node_display.node_id == source_node_id
|
148
|
-
][0]
|
149
|
-
except IndexError:
|
150
|
-
source_node_display = None
|
151
|
-
|
152
|
-
synthetic_target_handle_id = str(
|
153
|
-
uuid4_from_hash(f"{self.workflow_id}|target_handle_id|{workflow_output_display.name}")
|
154
|
-
)
|
155
|
-
synthetic_display_data = NodeDisplayData().dict()
|
156
|
-
synthetic_node_label = "Final Output"
|
157
|
-
nodes.append(
|
158
|
-
{
|
159
|
-
"id": str(final_output_node_id),
|
160
|
-
"type": "TERMINAL",
|
161
|
-
"data": {
|
162
|
-
"label": synthetic_node_label,
|
163
|
-
"name": workflow_output_display.name,
|
164
|
-
"target_handle_id": synthetic_target_handle_id,
|
165
|
-
"output_id": str(workflow_output_display.id),
|
166
|
-
"output_type": inferred_type,
|
167
|
-
"node_input_id": str(node_input.id),
|
168
|
-
},
|
169
|
-
"inputs": [node_input.dict()],
|
170
|
-
"display_data": synthetic_display_data,
|
171
|
-
"base": final_output_node_base,
|
172
|
-
"definition": None,
|
173
|
-
}
|
174
|
-
)
|
175
|
-
|
176
|
-
if source_node_display:
|
177
|
-
if isinstance(source_node_display, BaseNodeVellumDisplay):
|
178
|
-
source_handle_id = source_node_display.get_source_handle_id(
|
179
|
-
port_displays=self.display_context.port_displays
|
180
|
-
)
|
181
|
-
else:
|
182
|
-
source_handle_id = source_node_display.get_node_port_display(
|
183
|
-
source_node_display._node.Ports.default
|
184
|
-
).id
|
185
|
-
|
186
|
-
synthetic_output_edges.append(
|
187
|
-
{
|
188
|
-
"id": str(uuid4_from_hash(f"{self.workflow_id}|edge_id|{workflow_output_display.name}")),
|
189
|
-
"source_node_id": str(source_node_display.node_id),
|
190
|
-
"source_handle_id": str(source_handle_id),
|
191
|
-
"target_node_id": str(final_output_node_id),
|
192
|
-
"target_handle_id": synthetic_target_handle_id,
|
193
|
-
"type": "DEFAULT",
|
194
|
-
}
|
195
|
-
)
|
196
|
-
|
197
|
-
output_variables.append(
|
198
|
-
{
|
199
|
-
"id": str(workflow_output_display.id),
|
200
|
-
"key": workflow_output_display.name,
|
201
|
-
"type": inferred_type,
|
202
|
-
}
|
203
|
-
)
|
204
|
-
|
205
|
-
# If there are terminal nodes with no workflow output reference,
|
206
|
-
# raise a serialization error
|
207
|
-
if len(unreferenced_final_output_node_outputs) > 0:
|
208
|
-
self.add_error(
|
209
|
-
ValueError("Unable to serialize terminal nodes that are not referenced by workflow outputs.")
|
210
|
-
)
|
211
|
-
|
212
|
-
# Add an edge for each edge in the workflow
|
213
|
-
for target_node, entrypoint_display in self.display_context.entrypoint_displays.items():
|
214
|
-
unadorned_target_node = get_unadorned_node(target_node)
|
215
|
-
target_node_display = self.display_context.node_displays[unadorned_target_node]
|
216
|
-
edges.append(
|
217
|
-
{
|
218
|
-
"id": str(entrypoint_display.edge_display.id),
|
219
|
-
"source_node_id": str(entrypoint_node_id),
|
220
|
-
"source_handle_id": str(entrypoint_node_source_handle_id),
|
221
|
-
"target_node_id": str(target_node_display.node_id),
|
222
|
-
"target_handle_id": str(target_node_display.get_trigger_id()),
|
223
|
-
"type": "DEFAULT",
|
224
|
-
}
|
225
|
-
)
|
226
|
-
|
227
|
-
for (source_node_port, target_node), edge_display in self.display_context.edge_displays.items():
|
228
|
-
unadorned_source_node_port = get_unadorned_port(source_node_port)
|
229
|
-
unadorned_target_node = get_unadorned_node(target_node)
|
230
|
-
|
231
|
-
source_node_port_display = self.display_context.port_displays[unadorned_source_node_port]
|
232
|
-
target_node_display = self.display_context.node_displays[unadorned_target_node]
|
233
|
-
|
234
|
-
edges.append(
|
235
|
-
{
|
236
|
-
"id": str(edge_display.id),
|
237
|
-
"source_node_id": str(source_node_port_display.node_id),
|
238
|
-
"source_handle_id": str(source_node_port_display.id),
|
239
|
-
"target_node_id": str(target_node_display.node_id),
|
240
|
-
"target_handle_id": str(
|
241
|
-
target_node_display.get_target_handle_id_by_source_node_id(source_node_port_display.node_id)
|
242
|
-
),
|
243
|
-
"type": "DEFAULT",
|
244
|
-
}
|
245
|
-
)
|
246
|
-
|
247
|
-
edges.extend(synthetic_output_edges)
|
248
|
-
|
249
|
-
return {
|
250
|
-
"workflow_raw_data": {
|
251
|
-
"nodes": nodes,
|
252
|
-
"edges": edges,
|
253
|
-
"display_data": self.display_context.workflow_display.display_data.dict(),
|
254
|
-
"definition": {
|
255
|
-
"name": self._workflow.__name__,
|
256
|
-
"module": cast(JsonArray, self._workflow.__module__.split(".")),
|
257
|
-
},
|
258
|
-
},
|
259
|
-
"input_variables": input_variables,
|
260
|
-
"state_variables": state_variables,
|
261
|
-
"output_variables": output_variables,
|
262
|
-
}
|
7
|
+
# DEPRECATED: Use BaseWorkflowDisplay instead - This file will be removed in 0.15.0
|
8
|
+
class VellumWorkflowDisplay(BaseWorkflowDisplay[WorkflowType], Generic[WorkflowType]):
|
9
|
+
pass
|
@@ -11,7 +11,7 @@ from vellum_ee.workflows.display.vellum import (
|
|
11
11
|
WorkflowMetaVellumDisplayOverrides,
|
12
12
|
WorkflowOutputVellumDisplayOverrides,
|
13
13
|
)
|
14
|
-
from vellum_ee.workflows.display.workflows
|
14
|
+
from vellum_ee.workflows.display.workflows import BaseWorkflowDisplay
|
15
15
|
|
16
16
|
from ..inputs import Inputs
|
17
17
|
from ..nodes.final_output import FinalOutput
|
@@ -19,7 +19,7 @@ from ..nodes.templating_node import TemplatingNode
|
|
19
19
|
from ..workflow import Workflow
|
20
20
|
|
21
21
|
|
22
|
-
class WorkflowDisplay(
|
22
|
+
class WorkflowDisplay(BaseWorkflowDisplay[Workflow]):
|
23
23
|
workflow_display = WorkflowMetaVellumDisplayOverrides(
|
24
24
|
entrypoint_node_id=UUID("0bf86989-13f2-438c-ab9c-d172e5771d31"),
|
25
25
|
entrypoint_node_source_handle_id=UUID("23448f09-81ad-4378-abbd-1cccff350627"),
|
@@ -1,40 +0,0 @@
|
|
1
|
-
from uuid import UUID
|
2
|
-
from typing import ClassVar, Dict, Optional
|
3
|
-
|
4
|
-
from vellum.workflows.nodes.utils import get_unadorned_node
|
5
|
-
from vellum.workflows.ports import Port
|
6
|
-
from vellum.workflows.types.generics import NodeType
|
7
|
-
from vellum_ee.workflows.display.editor.types import NodeDisplayComment, NodeDisplayData
|
8
|
-
from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
|
9
|
-
from vellum_ee.workflows.display.nodes.types import PortDisplay
|
10
|
-
|
11
|
-
|
12
|
-
class BaseNodeVellumDisplay(BaseNodeDisplay[NodeType]):
|
13
|
-
# Used to explicitly set display data for a node
|
14
|
-
display_data: ClassVar[Optional[NodeDisplayData]] = None
|
15
|
-
|
16
|
-
def get_display_data(self) -> NodeDisplayData:
|
17
|
-
explicit_value = self._get_explicit_node_display_attr("display_data", NodeDisplayData)
|
18
|
-
docstring = self._node.__doc__
|
19
|
-
|
20
|
-
if explicit_value and explicit_value.comment and docstring:
|
21
|
-
comment = (
|
22
|
-
NodeDisplayComment(value=docstring, expanded=explicit_value.comment.expanded)
|
23
|
-
if explicit_value.comment.expanded
|
24
|
-
else NodeDisplayComment(value=docstring)
|
25
|
-
)
|
26
|
-
return NodeDisplayData(
|
27
|
-
position=explicit_value.position,
|
28
|
-
width=explicit_value.width,
|
29
|
-
height=explicit_value.height,
|
30
|
-
comment=comment,
|
31
|
-
)
|
32
|
-
|
33
|
-
return explicit_value if explicit_value else NodeDisplayData()
|
34
|
-
|
35
|
-
def get_source_handle_id(self, port_displays: Dict[Port, PortDisplay]) -> UUID:
|
36
|
-
unadorned_node = get_unadorned_node(self._node)
|
37
|
-
default_port = unadorned_node.Ports.default
|
38
|
-
|
39
|
-
default_port_display = port_displays[default_port]
|
40
|
-
return default_port_display.id
|
File without changes
|
File without changes
|
File without changes
|