vellum-ai 0.14.44__py3-none-any.whl → 0.14.46__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/core/pydantic_utilities.py +7 -1
- vellum/workflows/nodes/bases/base.py +1 -0
- vellum/workflows/nodes/bases/tests/test_base_node.py +20 -0
- vellum/workflows/nodes/displayable/bases/prompt_deployment_node.py +8 -14
- vellum/workflows/nodes/displayable/code_execution_node/tests/test_code_execution_node.py +62 -0
- vellum/workflows/nodes/displayable/code_execution_node/utils.py +3 -54
- vellum/workflows/nodes/displayable/tests/test_text_prompt_deployment_node.py +5 -6
- vellum/workflows/nodes/utils.py +4 -0
- vellum/workflows/ports/port.py +13 -3
- vellum/workflows/types/code_execution_node_wrappers.py +64 -0
- vellum/workflows/types/tests/test_utils.py +3 -3
- vellum/workflows/types/utils.py +31 -10
- vellum/workflows/vellum_client.py +19 -7
- {vellum_ai-0.14.44.dist-info → vellum_ai-0.14.46.dist-info}/METADATA +1 -1
- {vellum_ai-0.14.44.dist-info → vellum_ai-0.14.46.dist-info}/RECORD +56 -53
- vellum_cli/config.py +7 -2
- vellum_cli/push.py +5 -1
- vellum_cli/tests/test_push.py +192 -8
- vellum_ee/workflows/display/nodes/base_node_display.py +4 -173
- vellum_ee/workflows/display/nodes/vellum/conditional_node.py +1 -1
- vellum_ee/workflows/display/nodes/vellum/final_output_node.py +2 -1
- vellum_ee/workflows/display/nodes/vellum/prompt_deployment_node.py +5 -6
- vellum_ee/workflows/display/nodes/vellum/retry_node.py +3 -3
- vellum_ee/workflows/display/nodes/vellum/subworkflow_deployment_node.py +5 -6
- vellum_ee/workflows/display/nodes/vellum/tests/test_prompt_deployment_node.py +106 -0
- vellum_ee/workflows/display/nodes/vellum/tests/test_subworkflow_deployment_node.py +109 -0
- vellum_ee/workflows/display/nodes/vellum/try_node.py +3 -3
- vellum_ee/workflows/display/tests/test_base_workflow_display.py +1 -0
- vellum_ee/workflows/display/tests/workflow_serialization/generic_nodes/test_adornments_serialization.py +73 -111
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_api_node_serialization.py +0 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_code_execution_node_serialization.py +0 -3
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_conditional_node_serialization.py +0 -4
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_default_state_serialization.py +0 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_error_node_serialization.py +0 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_generic_node_serialization.py +0 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_guardrail_node_serialization.py +0 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_inline_subworkflow_serialization.py +18 -2
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_map_node_serialization.py +10 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_merge_node_serialization.py +0 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_prompt_deployment_serialization.py +2 -3
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_search_node_serialization.py +0 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_subworkflow_deployment_serialization.py +2 -3
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_templating_node_serialization.py +0 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_terminal_node_serialization.py +1 -2
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_try_node_serialization.py +0 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_complex_terminal_node_serialization.py +5 -55
- vellum_ee/workflows/display/types.py +3 -0
- vellum_ee/workflows/display/utils/expressions.py +222 -2
- vellum_ee/workflows/display/utils/vellum.py +1 -79
- vellum_ee/workflows/display/workflows/base_workflow_display.py +59 -37
- vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py +3 -0
- vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +98 -0
- {vellum_ai-0.14.44.dist-info → vellum_ai-0.14.46.dist-info}/LICENSE +0 -0
- {vellum_ai-0.14.44.dist-info → vellum_ai-0.14.46.dist-info}/WHEEL +0 -0
- {vellum_ai-0.14.44.dist-info → vellum_ai-0.14.46.dist-info}/entry_points.txt +0 -0
@@ -1,12 +1,98 @@
|
|
1
|
-
from typing import TYPE_CHECKING
|
1
|
+
from typing import TYPE_CHECKING, Any
|
2
2
|
|
3
|
+
from vellum.client.types.logical_operator import LogicalOperator
|
3
4
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
5
|
+
from vellum.workflows.expressions.accessor import AccessorExpression
|
6
|
+
from vellum.workflows.expressions.and_ import AndExpression
|
7
|
+
from vellum.workflows.expressions.begins_with import BeginsWithExpression
|
8
|
+
from vellum.workflows.expressions.between import BetweenExpression
|
9
|
+
from vellum.workflows.expressions.coalesce_expression import CoalesceExpression
|
10
|
+
from vellum.workflows.expressions.contains import ContainsExpression
|
11
|
+
from vellum.workflows.expressions.does_not_begin_with import DoesNotBeginWithExpression
|
12
|
+
from vellum.workflows.expressions.does_not_contain import DoesNotContainExpression
|
13
|
+
from vellum.workflows.expressions.does_not_end_with import DoesNotEndWithExpression
|
14
|
+
from vellum.workflows.expressions.does_not_equal import DoesNotEqualExpression
|
15
|
+
from vellum.workflows.expressions.ends_with import EndsWithExpression
|
16
|
+
from vellum.workflows.expressions.equals import EqualsExpression
|
17
|
+
from vellum.workflows.expressions.greater_than import GreaterThanExpression
|
18
|
+
from vellum.workflows.expressions.greater_than_or_equal_to import GreaterThanOrEqualToExpression
|
19
|
+
from vellum.workflows.expressions.in_ import InExpression
|
20
|
+
from vellum.workflows.expressions.is_nil import IsNilExpression
|
21
|
+
from vellum.workflows.expressions.is_not_nil import IsNotNilExpression
|
22
|
+
from vellum.workflows.expressions.is_not_null import IsNotNullExpression
|
23
|
+
from vellum.workflows.expressions.is_not_undefined import IsNotUndefinedExpression
|
24
|
+
from vellum.workflows.expressions.is_null import IsNullExpression
|
25
|
+
from vellum.workflows.expressions.is_undefined import IsUndefinedExpression
|
26
|
+
from vellum.workflows.expressions.less_than import LessThanExpression
|
27
|
+
from vellum.workflows.expressions.less_than_or_equal_to import LessThanOrEqualToExpression
|
28
|
+
from vellum.workflows.expressions.not_between import NotBetweenExpression
|
29
|
+
from vellum.workflows.expressions.not_in import NotInExpression
|
30
|
+
from vellum.workflows.expressions.or_ import OrExpression
|
31
|
+
from vellum.workflows.expressions.parse_json import ParseJsonExpression
|
32
|
+
from vellum.workflows.nodes.displayable.bases.utils import primitive_to_vellum_value
|
33
|
+
from vellum.workflows.references.constant import ConstantValueReference
|
34
|
+
from vellum.workflows.references.execution_count import ExecutionCountReference
|
4
35
|
from vellum.workflows.references.lazy import LazyReference
|
36
|
+
from vellum.workflows.references.output import OutputReference
|
37
|
+
from vellum.workflows.references.state_value import StateValueReference
|
38
|
+
from vellum.workflows.references.vellum_secret import VellumSecretReference
|
39
|
+
from vellum.workflows.references.workflow_input import WorkflowInputReference
|
40
|
+
from vellum.workflows.types.core import JsonObject
|
41
|
+
from vellum_ee.workflows.display.utils.exceptions import UnsupportedSerializationException
|
5
42
|
|
6
43
|
if TYPE_CHECKING:
|
7
44
|
from vellum_ee.workflows.display.types import WorkflowDisplayContext
|
8
45
|
|
9
46
|
|
47
|
+
def convert_descriptor_to_operator(descriptor: BaseDescriptor) -> LogicalOperator:
|
48
|
+
if isinstance(descriptor, EqualsExpression):
|
49
|
+
return "="
|
50
|
+
elif isinstance(descriptor, DoesNotEqualExpression):
|
51
|
+
return "!="
|
52
|
+
elif isinstance(descriptor, LessThanExpression):
|
53
|
+
return "<"
|
54
|
+
elif isinstance(descriptor, GreaterThanExpression):
|
55
|
+
return ">"
|
56
|
+
elif isinstance(descriptor, LessThanOrEqualToExpression):
|
57
|
+
return "<="
|
58
|
+
elif isinstance(descriptor, GreaterThanOrEqualToExpression):
|
59
|
+
return ">="
|
60
|
+
elif isinstance(descriptor, ContainsExpression):
|
61
|
+
return "contains"
|
62
|
+
elif isinstance(descriptor, BeginsWithExpression):
|
63
|
+
return "beginsWith"
|
64
|
+
elif isinstance(descriptor, EndsWithExpression):
|
65
|
+
return "endsWith"
|
66
|
+
elif isinstance(descriptor, DoesNotContainExpression):
|
67
|
+
return "doesNotContain"
|
68
|
+
elif isinstance(descriptor, DoesNotBeginWithExpression):
|
69
|
+
return "doesNotBeginWith"
|
70
|
+
elif isinstance(descriptor, DoesNotEndWithExpression):
|
71
|
+
return "doesNotEndWith"
|
72
|
+
elif isinstance(descriptor, (IsNullExpression, IsNilExpression, IsUndefinedExpression)):
|
73
|
+
return "null"
|
74
|
+
elif isinstance(descriptor, (IsNotNullExpression, IsNotNilExpression, IsNotUndefinedExpression)):
|
75
|
+
return "notNull"
|
76
|
+
elif isinstance(descriptor, InExpression):
|
77
|
+
return "in"
|
78
|
+
elif isinstance(descriptor, NotInExpression):
|
79
|
+
return "notIn"
|
80
|
+
elif isinstance(descriptor, BetweenExpression):
|
81
|
+
return "between"
|
82
|
+
elif isinstance(descriptor, NotBetweenExpression):
|
83
|
+
return "notBetween"
|
84
|
+
elif isinstance(descriptor, AndExpression):
|
85
|
+
return "and"
|
86
|
+
elif isinstance(descriptor, OrExpression):
|
87
|
+
return "or"
|
88
|
+
elif isinstance(descriptor, CoalesceExpression):
|
89
|
+
return "coalesce"
|
90
|
+
elif isinstance(descriptor, ParseJsonExpression):
|
91
|
+
return "parseJson"
|
92
|
+
else:
|
93
|
+
raise ValueError(f"Unsupported descriptor type: {descriptor}")
|
94
|
+
|
95
|
+
|
10
96
|
def get_child_descriptor(value: LazyReference, display_context: "WorkflowDisplayContext") -> BaseDescriptor:
|
11
97
|
if isinstance(value._get, str):
|
12
98
|
reference_parts = value._get.split(".")
|
@@ -21,10 +107,144 @@ def get_child_descriptor(value: LazyReference, display_context: "WorkflowDisplay
|
|
21
107
|
)
|
22
108
|
|
23
109
|
node_class_name = ".".join(reference_parts[:-2])
|
24
|
-
for node in display_context.
|
110
|
+
for node in display_context.global_node_displays.keys():
|
25
111
|
if node.__name__ == node_class_name:
|
26
112
|
return getattr(node.Outputs, output_name)
|
27
113
|
|
28
114
|
raise Exception(f"Failed to parse lazy reference: {value._get}")
|
29
115
|
|
30
116
|
return value._get()
|
117
|
+
|
118
|
+
|
119
|
+
def serialize_condition(display_context: "WorkflowDisplayContext", condition: BaseDescriptor) -> JsonObject:
|
120
|
+
if isinstance(
|
121
|
+
condition,
|
122
|
+
(
|
123
|
+
IsNullExpression,
|
124
|
+
IsNotNullExpression,
|
125
|
+
IsNilExpression,
|
126
|
+
IsNotNilExpression,
|
127
|
+
IsUndefinedExpression,
|
128
|
+
IsNotUndefinedExpression,
|
129
|
+
ParseJsonExpression,
|
130
|
+
),
|
131
|
+
):
|
132
|
+
lhs = serialize_value(display_context, condition._expression)
|
133
|
+
return {
|
134
|
+
"type": "UNARY_EXPRESSION",
|
135
|
+
"lhs": lhs,
|
136
|
+
"operator": convert_descriptor_to_operator(condition),
|
137
|
+
}
|
138
|
+
elif isinstance(condition, (BetweenExpression, NotBetweenExpression)):
|
139
|
+
base = serialize_value(display_context, condition._value)
|
140
|
+
lhs = serialize_value(display_context, condition._start)
|
141
|
+
rhs = serialize_value(display_context, condition._end)
|
142
|
+
|
143
|
+
return {
|
144
|
+
"type": "TERNARY_EXPRESSION",
|
145
|
+
"base": base,
|
146
|
+
"operator": convert_descriptor_to_operator(condition),
|
147
|
+
"lhs": lhs,
|
148
|
+
"rhs": rhs,
|
149
|
+
}
|
150
|
+
elif isinstance(
|
151
|
+
condition,
|
152
|
+
(
|
153
|
+
AndExpression,
|
154
|
+
BeginsWithExpression,
|
155
|
+
CoalesceExpression,
|
156
|
+
ContainsExpression,
|
157
|
+
DoesNotBeginWithExpression,
|
158
|
+
DoesNotContainExpression,
|
159
|
+
DoesNotEndWithExpression,
|
160
|
+
DoesNotEqualExpression,
|
161
|
+
EndsWithExpression,
|
162
|
+
EqualsExpression,
|
163
|
+
GreaterThanExpression,
|
164
|
+
GreaterThanOrEqualToExpression,
|
165
|
+
InExpression,
|
166
|
+
LessThanExpression,
|
167
|
+
LessThanOrEqualToExpression,
|
168
|
+
NotInExpression,
|
169
|
+
OrExpression,
|
170
|
+
),
|
171
|
+
):
|
172
|
+
lhs = serialize_value(display_context, condition._lhs)
|
173
|
+
rhs = serialize_value(display_context, condition._rhs)
|
174
|
+
|
175
|
+
return {
|
176
|
+
"type": "BINARY_EXPRESSION",
|
177
|
+
"lhs": lhs,
|
178
|
+
"operator": convert_descriptor_to_operator(condition),
|
179
|
+
"rhs": rhs,
|
180
|
+
}
|
181
|
+
elif isinstance(condition, AccessorExpression):
|
182
|
+
return {
|
183
|
+
"type": "BINARY_EXPRESSION",
|
184
|
+
"lhs": serialize_value(display_context, condition._base),
|
185
|
+
"operator": "accessField",
|
186
|
+
"rhs": serialize_value(display_context, condition._field),
|
187
|
+
}
|
188
|
+
|
189
|
+
raise UnsupportedSerializationException(f"Unsupported condition type: {condition.__class__.__name__}")
|
190
|
+
|
191
|
+
|
192
|
+
def serialize_value(display_context: "WorkflowDisplayContext", value: Any) -> JsonObject:
|
193
|
+
if isinstance(value, ConstantValueReference):
|
194
|
+
return serialize_value(display_context, value._value)
|
195
|
+
|
196
|
+
if isinstance(value, LazyReference):
|
197
|
+
child_descriptor = get_child_descriptor(value, display_context)
|
198
|
+
return serialize_value(display_context, child_descriptor)
|
199
|
+
|
200
|
+
if isinstance(value, WorkflowInputReference):
|
201
|
+
workflow_input_display = display_context.global_workflow_input_displays[value]
|
202
|
+
return {
|
203
|
+
"type": "WORKFLOW_INPUT",
|
204
|
+
"input_variable_id": str(workflow_input_display.id),
|
205
|
+
}
|
206
|
+
|
207
|
+
if isinstance(value, StateValueReference):
|
208
|
+
state_value_display = display_context.global_state_value_displays[value]
|
209
|
+
return {
|
210
|
+
"type": "STATE_VALUE",
|
211
|
+
"state_variable_id": str(state_value_display.id),
|
212
|
+
}
|
213
|
+
|
214
|
+
if isinstance(value, OutputReference):
|
215
|
+
upstream_node, output_display = display_context.global_node_output_displays[value]
|
216
|
+
upstream_node_display = display_context.global_node_displays[upstream_node]
|
217
|
+
|
218
|
+
return {
|
219
|
+
"type": "NODE_OUTPUT",
|
220
|
+
"node_id": str(upstream_node_display.node_id),
|
221
|
+
"node_output_id": str(output_display.id),
|
222
|
+
}
|
223
|
+
|
224
|
+
if isinstance(value, VellumSecretReference):
|
225
|
+
return {
|
226
|
+
"type": "VELLUM_SECRET",
|
227
|
+
"vellum_secret_name": value.name,
|
228
|
+
}
|
229
|
+
|
230
|
+
if isinstance(value, ExecutionCountReference):
|
231
|
+
node_class_display = display_context.global_node_displays[value.node_class]
|
232
|
+
|
233
|
+
return {
|
234
|
+
"type": "EXECUTION_COUNTER",
|
235
|
+
"node_id": str(node_class_display.node_id),
|
236
|
+
}
|
237
|
+
|
238
|
+
if isinstance(value, dict) and any(isinstance(v, BaseDescriptor) for v in value.values()):
|
239
|
+
raise ValueError("Nested references are not supported.")
|
240
|
+
|
241
|
+
if not isinstance(value, BaseDescriptor):
|
242
|
+
vellum_value = primitive_to_vellum_value(value)
|
243
|
+
return {
|
244
|
+
"type": "CONSTANT_VALUE",
|
245
|
+
"value": vellum_value.dict(),
|
246
|
+
}
|
247
|
+
|
248
|
+
# If it's not any of the references we know about,
|
249
|
+
# then try to serialize it as a nested value
|
250
|
+
return serialize_condition(display_context, value)
|
@@ -2,36 +2,9 @@ from typing import TYPE_CHECKING, Any, Literal, Optional, Union
|
|
2
2
|
|
3
3
|
from vellum.client.core.pydantic_utilities import UniversalBaseModel
|
4
4
|
from vellum.client.types.array_vellum_value import ArrayVellumValue
|
5
|
-
from vellum.client.types.logical_operator import LogicalOperator
|
6
5
|
from vellum.client.types.vellum_value import VellumValue
|
7
6
|
from vellum.client.types.vellum_variable_type import VellumVariableType
|
8
7
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
9
|
-
from vellum.workflows.expressions.and_ import AndExpression
|
10
|
-
from vellum.workflows.expressions.begins_with import BeginsWithExpression
|
11
|
-
from vellum.workflows.expressions.between import BetweenExpression
|
12
|
-
from vellum.workflows.expressions.coalesce_expression import CoalesceExpression
|
13
|
-
from vellum.workflows.expressions.contains import ContainsExpression
|
14
|
-
from vellum.workflows.expressions.does_not_begin_with import DoesNotBeginWithExpression
|
15
|
-
from vellum.workflows.expressions.does_not_contain import DoesNotContainExpression
|
16
|
-
from vellum.workflows.expressions.does_not_end_with import DoesNotEndWithExpression
|
17
|
-
from vellum.workflows.expressions.does_not_equal import DoesNotEqualExpression
|
18
|
-
from vellum.workflows.expressions.ends_with import EndsWithExpression
|
19
|
-
from vellum.workflows.expressions.equals import EqualsExpression
|
20
|
-
from vellum.workflows.expressions.greater_than import GreaterThanExpression
|
21
|
-
from vellum.workflows.expressions.greater_than_or_equal_to import GreaterThanOrEqualToExpression
|
22
|
-
from vellum.workflows.expressions.in_ import InExpression
|
23
|
-
from vellum.workflows.expressions.is_nil import IsNilExpression
|
24
|
-
from vellum.workflows.expressions.is_not_nil import IsNotNilExpression
|
25
|
-
from vellum.workflows.expressions.is_not_null import IsNotNullExpression
|
26
|
-
from vellum.workflows.expressions.is_not_undefined import IsNotUndefinedExpression
|
27
|
-
from vellum.workflows.expressions.is_null import IsNullExpression
|
28
|
-
from vellum.workflows.expressions.is_undefined import IsUndefinedExpression
|
29
|
-
from vellum.workflows.expressions.less_than import LessThanExpression
|
30
|
-
from vellum.workflows.expressions.less_than_or_equal_to import LessThanOrEqualToExpression
|
31
|
-
from vellum.workflows.expressions.not_between import NotBetweenExpression
|
32
|
-
from vellum.workflows.expressions.not_in import NotInExpression
|
33
|
-
from vellum.workflows.expressions.or_ import OrExpression
|
34
|
-
from vellum.workflows.expressions.parse_json import ParseJsonExpression
|
35
8
|
from vellum.workflows.nodes.bases.base import BaseNode
|
36
9
|
from vellum.workflows.nodes.displayable.bases.utils import primitive_to_vellum_value
|
37
10
|
from vellum.workflows.references import OutputReference, WorkflowInputReference
|
@@ -40,7 +13,6 @@ from vellum.workflows.references.lazy import LazyReference
|
|
40
13
|
from vellum.workflows.references.node import NodeReference
|
41
14
|
from vellum.workflows.references.vellum_secret import VellumSecretReference
|
42
15
|
from vellum.workflows.utils.vellum_variables import primitive_type_to_vellum_variable_type
|
43
|
-
from vellum.workflows.vellum_client import create_vellum_client
|
44
16
|
from vellum_ee.workflows.display.utils.exceptions import UnsupportedSerializationException
|
45
17
|
from vellum_ee.workflows.display.utils.expressions import get_child_descriptor
|
46
18
|
|
@@ -145,8 +117,7 @@ def create_node_input_value_pointer_rule(
|
|
145
117
|
workflow_input_display = display_context.global_workflow_input_displays[value]
|
146
118
|
return InputVariablePointer(data=InputVariableData(input_variable_id=str(workflow_input_display.id)))
|
147
119
|
if isinstance(value, VellumSecretReference):
|
148
|
-
|
149
|
-
workspace_secret = vellum_client.workspace_secrets.retrieve(
|
120
|
+
workspace_secret = display_context.client.workspace_secrets.retrieve(
|
150
121
|
id=value.name,
|
151
122
|
)
|
152
123
|
return WorkspaceSecretPointer(
|
@@ -166,52 +137,3 @@ def create_node_input_value_pointer_rule(
|
|
166
137
|
return ConstantValuePointer(type="CONSTANT_VALUE", data=vellum_value)
|
167
138
|
|
168
139
|
raise UnsupportedSerializationException(f"Unsupported descriptor type: {value.__class__.__name__}")
|
169
|
-
|
170
|
-
|
171
|
-
def convert_descriptor_to_operator(descriptor: BaseDescriptor) -> LogicalOperator:
|
172
|
-
if isinstance(descriptor, EqualsExpression):
|
173
|
-
return "="
|
174
|
-
elif isinstance(descriptor, DoesNotEqualExpression):
|
175
|
-
return "!="
|
176
|
-
elif isinstance(descriptor, LessThanExpression):
|
177
|
-
return "<"
|
178
|
-
elif isinstance(descriptor, GreaterThanExpression):
|
179
|
-
return ">"
|
180
|
-
elif isinstance(descriptor, LessThanOrEqualToExpression):
|
181
|
-
return "<="
|
182
|
-
elif isinstance(descriptor, GreaterThanOrEqualToExpression):
|
183
|
-
return ">="
|
184
|
-
elif isinstance(descriptor, ContainsExpression):
|
185
|
-
return "contains"
|
186
|
-
elif isinstance(descriptor, BeginsWithExpression):
|
187
|
-
return "beginsWith"
|
188
|
-
elif isinstance(descriptor, EndsWithExpression):
|
189
|
-
return "endsWith"
|
190
|
-
elif isinstance(descriptor, DoesNotContainExpression):
|
191
|
-
return "doesNotContain"
|
192
|
-
elif isinstance(descriptor, DoesNotBeginWithExpression):
|
193
|
-
return "doesNotBeginWith"
|
194
|
-
elif isinstance(descriptor, DoesNotEndWithExpression):
|
195
|
-
return "doesNotEndWith"
|
196
|
-
elif isinstance(descriptor, (IsNullExpression, IsNilExpression, IsUndefinedExpression)):
|
197
|
-
return "null"
|
198
|
-
elif isinstance(descriptor, (IsNotNullExpression, IsNotNilExpression, IsNotUndefinedExpression)):
|
199
|
-
return "notNull"
|
200
|
-
elif isinstance(descriptor, InExpression):
|
201
|
-
return "in"
|
202
|
-
elif isinstance(descriptor, NotInExpression):
|
203
|
-
return "notIn"
|
204
|
-
elif isinstance(descriptor, BetweenExpression):
|
205
|
-
return "between"
|
206
|
-
elif isinstance(descriptor, NotBetweenExpression):
|
207
|
-
return "notBetween"
|
208
|
-
elif isinstance(descriptor, AndExpression):
|
209
|
-
return "and"
|
210
|
-
elif isinstance(descriptor, OrExpression):
|
211
|
-
return "or"
|
212
|
-
elif isinstance(descriptor, CoalesceExpression):
|
213
|
-
return "coalesce"
|
214
|
-
elif isinstance(descriptor, ParseJsonExpression):
|
215
|
-
return "parseJson"
|
216
|
-
else:
|
217
|
-
raise ValueError(f"Unsupported descriptor type: {descriptor}")
|
@@ -6,6 +6,7 @@ import logging
|
|
6
6
|
from uuid import UUID
|
7
7
|
from typing import Any, Dict, ForwardRef, Generic, Iterator, List, Optional, Tuple, Type, TypeVar, Union, cast, get_args
|
8
8
|
|
9
|
+
from vellum.client import Vellum as VellumClient
|
9
10
|
from vellum.workflows import BaseWorkflow
|
10
11
|
from vellum.workflows.constants import undefined
|
11
12
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
@@ -21,6 +22,7 @@ from vellum.workflows.types.core import JsonArray, JsonObject
|
|
21
22
|
from vellum.workflows.types.generics import WorkflowType
|
22
23
|
from vellum.workflows.types.utils import get_original_base
|
23
24
|
from vellum.workflows.utils.uuids import uuid4_from_hash
|
25
|
+
from vellum.workflows.vellum_client import create_vellum_client
|
24
26
|
from vellum_ee.workflows.display.base import (
|
25
27
|
EdgeDisplay,
|
26
28
|
EntrypointDisplay,
|
@@ -46,6 +48,7 @@ from vellum_ee.workflows.display.types import (
|
|
46
48
|
WorkflowInputsDisplays,
|
47
49
|
WorkflowOutputDisplays,
|
48
50
|
)
|
51
|
+
from vellum_ee.workflows.display.utils.expressions import serialize_value
|
49
52
|
from vellum_ee.workflows.display.utils.registry import register_workflow_display_class
|
50
53
|
from vellum_ee.workflows.display.utils.vellum import infer_vellum_variable_type
|
51
54
|
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
@@ -83,9 +86,16 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
|
|
83
86
|
self,
|
84
87
|
*,
|
85
88
|
parent_display_context: Optional[WorkflowDisplayContext] = None,
|
89
|
+
client: Optional[VellumClient] = None,
|
86
90
|
dry_run: bool = False,
|
87
91
|
):
|
88
92
|
self._parent_display_context = parent_display_context
|
93
|
+
self._client = client or (
|
94
|
+
# propagate the client from the parent display context if it is not provided
|
95
|
+
self._parent_display_context.client
|
96
|
+
if self._parent_display_context
|
97
|
+
else create_vellum_client()
|
98
|
+
)
|
89
99
|
self._errors: List[Exception] = []
|
90
100
|
self._dry_run = dry_run
|
91
101
|
|
@@ -124,26 +134,24 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
|
|
124
134
|
}
|
125
135
|
)
|
126
136
|
|
127
|
-
|
137
|
+
serialized_nodes: Dict[UUID, JsonObject] = {}
|
128
138
|
edges: JsonArray = []
|
129
139
|
|
130
140
|
# Add a single synthetic node for the workflow entrypoint
|
131
141
|
entrypoint_node_id = self.display_context.workflow_display.entrypoint_node_id
|
132
142
|
entrypoint_node_source_handle_id = self.display_context.workflow_display.entrypoint_node_source_handle_id
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
"
|
139
|
-
|
140
|
-
"source_handle_id": str(entrypoint_node_source_handle_id),
|
141
|
-
},
|
142
|
-
"display_data": self.display_context.workflow_display.entrypoint_node_display.dict(),
|
143
|
-
"base": None,
|
144
|
-
"definition": None,
|
143
|
+
serialized_nodes[entrypoint_node_id] = {
|
144
|
+
"id": str(entrypoint_node_id),
|
145
|
+
"type": "ENTRYPOINT",
|
146
|
+
"inputs": [],
|
147
|
+
"data": {
|
148
|
+
"label": "Entrypoint Node",
|
149
|
+
"source_handle_id": str(entrypoint_node_source_handle_id),
|
145
150
|
},
|
146
|
-
|
151
|
+
"display_data": self.display_context.workflow_display.entrypoint_node_display.dict(),
|
152
|
+
"base": None,
|
153
|
+
"definition": None,
|
154
|
+
}
|
147
155
|
|
148
156
|
# Add all the nodes in the workflow
|
149
157
|
for node in self._workflow.get_nodes():
|
@@ -155,7 +163,7 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
|
|
155
163
|
self.add_error(e)
|
156
164
|
continue
|
157
165
|
|
158
|
-
|
166
|
+
serialized_nodes[node_display.node_id] = serialized_node
|
159
167
|
|
160
168
|
# Add all unused nodes in the workflow
|
161
169
|
for node in self._workflow.get_unused_nodes():
|
@@ -167,10 +175,11 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
|
|
167
175
|
self.add_error(e)
|
168
176
|
continue
|
169
177
|
|
170
|
-
|
178
|
+
serialized_nodes[node_display.node_id] = serialized_node
|
171
179
|
|
172
180
|
synthetic_output_edges: JsonArray = []
|
173
181
|
output_variables: JsonArray = []
|
182
|
+
output_values: JsonArray = []
|
174
183
|
final_output_nodes = [
|
175
184
|
node for node in self.display_context.node_displays.keys() if issubclass(node, FinalOutputNode)
|
176
185
|
]
|
@@ -185,9 +194,9 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
|
|
185
194
|
for workflow_output, workflow_output_display in self.display_context.workflow_output_displays.items():
|
186
195
|
final_output_node_id = uuid4_from_hash(f"{self.workflow_id}|node_id|{workflow_output.name}")
|
187
196
|
inferred_type = infer_vellum_variable_type(workflow_output)
|
188
|
-
|
189
197
|
# Remove the terminal node output from the unreferenced set
|
190
|
-
|
198
|
+
if isinstance(workflow_output.instance, OutputReference):
|
199
|
+
unreferenced_final_output_node_outputs.discard(workflow_output.instance)
|
191
200
|
|
192
201
|
if workflow_output.instance not in final_output_node_outputs:
|
193
202
|
# Create a synthetic terminal node only if there is no terminal node for this output
|
@@ -220,24 +229,22 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
|
|
220
229
|
)
|
221
230
|
synthetic_display_data = NodeDisplayData().dict()
|
222
231
|
synthetic_node_label = "Final Output"
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
"
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
}
|
240
|
-
)
|
232
|
+
serialized_nodes[final_output_node_id] = {
|
233
|
+
"id": str(final_output_node_id),
|
234
|
+
"type": "TERMINAL",
|
235
|
+
"data": {
|
236
|
+
"label": synthetic_node_label,
|
237
|
+
"name": workflow_output_display.name,
|
238
|
+
"target_handle_id": synthetic_target_handle_id,
|
239
|
+
"output_id": str(workflow_output_display.id),
|
240
|
+
"output_type": inferred_type,
|
241
|
+
"node_input_id": str(node_input.id),
|
242
|
+
},
|
243
|
+
"inputs": [node_input.dict()],
|
244
|
+
"display_data": synthetic_display_data,
|
245
|
+
"base": final_output_node_base,
|
246
|
+
"definition": None,
|
247
|
+
}
|
241
248
|
|
242
249
|
if source_node_display:
|
243
250
|
source_handle_id = source_node_display.get_source_handle_id(
|
@@ -255,6 +262,19 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
|
|
255
262
|
}
|
256
263
|
)
|
257
264
|
|
265
|
+
elif isinstance(workflow_output.instance, OutputReference):
|
266
|
+
terminal_node_id = workflow_output.instance.outputs_class._node_class.__id__
|
267
|
+
serialized_terminal_node = serialized_nodes.get(terminal_node_id)
|
268
|
+
if serialized_terminal_node and isinstance(serialized_terminal_node["data"], dict):
|
269
|
+
serialized_terminal_node["data"]["name"] = workflow_output_display.name
|
270
|
+
|
271
|
+
output_values.append(
|
272
|
+
{
|
273
|
+
"output_variable_id": str(workflow_output_display.id),
|
274
|
+
"value": serialize_value(self.display_context, workflow_output.instance),
|
275
|
+
}
|
276
|
+
)
|
277
|
+
|
258
278
|
output_variables.append(
|
259
279
|
{
|
260
280
|
"id": str(workflow_output_display.id),
|
@@ -309,13 +329,14 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
|
|
309
329
|
|
310
330
|
return {
|
311
331
|
"workflow_raw_data": {
|
312
|
-
"nodes":
|
332
|
+
"nodes": list(serialized_nodes.values()),
|
313
333
|
"edges": edges,
|
314
334
|
"display_data": self.display_context.workflow_display.display_data.dict(),
|
315
335
|
"definition": {
|
316
336
|
"name": self._workflow.__name__,
|
317
337
|
"module": cast(JsonArray, self._workflow.__module__.split(".")),
|
318
338
|
},
|
339
|
+
"output_values": output_values,
|
319
340
|
},
|
320
341
|
"input_variables": input_variables,
|
321
342
|
"state_variables": state_variables,
|
@@ -482,6 +503,7 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
|
|
482
503
|
)
|
483
504
|
|
484
505
|
return WorkflowDisplayContext(
|
506
|
+
client=self._client,
|
485
507
|
workflow_display=workflow_meta_display,
|
486
508
|
workflow_input_displays=workflow_input_displays,
|
487
509
|
global_workflow_input_displays=global_workflow_input_displays,
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import types
|
2
2
|
from typing import TYPE_CHECKING, Generic, Optional, Type, TypeVar
|
3
3
|
|
4
|
+
from vellum.client import Vellum as VellumClient
|
4
5
|
from vellum.workflows.types.generics import WorkflowType
|
5
6
|
from vellum_ee.workflows.display.types import WorkflowDisplayContext
|
6
7
|
from vellum_ee.workflows.display.utils.registry import get_from_workflow_display_registry
|
@@ -35,6 +36,7 @@ def get_workflow_display(
|
|
35
36
|
*,
|
36
37
|
workflow_class: Type[WorkflowType],
|
37
38
|
parent_display_context: Optional[WorkflowDisplayContext] = None,
|
39
|
+
client: Optional[VellumClient] = None,
|
38
40
|
dry_run: bool = False,
|
39
41
|
# DEPRECATED: The following arguments will be removed in 0.15.0
|
40
42
|
root_workflow_class: Optional[Type[WorkflowType]] = None,
|
@@ -42,5 +44,6 @@ def get_workflow_display(
|
|
42
44
|
) -> "BaseWorkflowDisplay":
|
43
45
|
return _get_workflow_display_class(workflow_class=workflow_class)(
|
44
46
|
parent_display_context=parent_display_context,
|
47
|
+
client=client,
|
45
48
|
dry_run=dry_run,
|
46
49
|
)
|