vellum-ai 0.14.9__py3-none-any.whl → 0.14.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.
- vellum/client/core/client_wrapper.py +1 -1
- vellum/utils/templating/render.py +4 -1
- vellum/workflows/events/workflow.py +3 -2
- vellum/workflows/nodes/core/templating_node/node.py +0 -1
- vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py +49 -0
- vellum/workflows/nodes/utils.py +14 -3
- vellum/workflows/runner/runner.py +1 -5
- {vellum_ai-0.14.9.dist-info → vellum_ai-0.14.10.dist-info}/METADATA +1 -1
- {vellum_ai-0.14.9.dist-info → vellum_ai-0.14.10.dist-info}/RECORD +15 -15
- vellum_ee/workflows/display/workflows/base_workflow_display.py +37 -13
- vellum_ee/workflows/display/workflows/tests/test_workflow_display.py +27 -0
- vellum_ee/workflows/tests/test_display_meta.py +2 -0
- {vellum_ai-0.14.9.dist-info → vellum_ai-0.14.10.dist-info}/LICENSE +0 -0
- {vellum_ai-0.14.9.dist-info → vellum_ai-0.14.10.dist-info}/WHEEL +0 -0
- {vellum_ai-0.14.9.dist-info → vellum_ai-0.14.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.14.
|
21
|
+
"X-Fern-SDK-Version": "0.14.10",
|
22
22
|
}
|
23
23
|
headers["X_API_KEY"] = self.api_key
|
24
24
|
return headers
|
@@ -2,6 +2,7 @@ import json
|
|
2
2
|
from typing import Any, Dict, Optional
|
3
3
|
|
4
4
|
from jinja2.sandbox import SandboxedEnvironment
|
5
|
+
from pydantic import BaseModel
|
5
6
|
|
6
7
|
from vellum.utils.templating.constants import FilterFunc
|
7
8
|
from vellum.utils.templating.exceptions import JinjaTemplateError
|
@@ -12,6 +13,9 @@ def finalize(obj: Any) -> str:
|
|
12
13
|
if isinstance(obj, (dict, list)):
|
13
14
|
return json.dumps(obj, cls=DefaultStateEncoder)
|
14
15
|
|
16
|
+
if isinstance(obj, BaseModel):
|
17
|
+
return json.dumps(obj.model_dump(), cls=DefaultStateEncoder)
|
18
|
+
|
15
19
|
return str(obj)
|
16
20
|
|
17
21
|
|
@@ -23,7 +27,6 @@ def render_sandboxed_jinja_template(
|
|
23
27
|
jinja_globals: Optional[Dict[str, Any]] = None,
|
24
28
|
) -> str:
|
25
29
|
"""Render a Jinja template within a sandboxed environment."""
|
26
|
-
|
27
30
|
try:
|
28
31
|
environment = SandboxedEnvironment(
|
29
32
|
keep_trailing_newline=True,
|
@@ -39,14 +39,15 @@ class _BaseWorkflowEvent(BaseEvent):
|
|
39
39
|
return self.body.workflow_definition
|
40
40
|
|
41
41
|
|
42
|
-
class
|
42
|
+
class NodeEventDisplayContext(UniversalBaseModel):
|
43
43
|
input_display: Dict[str, UUID]
|
44
44
|
output_display: Dict[str, UUID]
|
45
45
|
port_display: Dict[str, UUID]
|
46
|
+
subworkflow_display: Optional["WorkflowEventDisplayContext"] = None
|
46
47
|
|
47
48
|
|
48
49
|
class WorkflowEventDisplayContext(UniversalBaseModel):
|
49
|
-
node_displays: Dict[str,
|
50
|
+
node_displays: Dict[str, NodeEventDisplayContext]
|
50
51
|
workflow_inputs: Dict[str, UUID]
|
51
52
|
workflow_outputs: Dict[str, UUID]
|
52
53
|
|
@@ -82,7 +82,6 @@ class TemplatingNode(BaseNode[StateType], Generic[StateType, _OutputType], metac
|
|
82
82
|
def run(self) -> Outputs:
|
83
83
|
rendered_template = self._render_template()
|
84
84
|
result = self._cast_rendered_template(rendered_template)
|
85
|
-
|
86
85
|
return self.Outputs(result=result)
|
87
86
|
|
88
87
|
def _render_template(self) -> str:
|
@@ -234,3 +234,52 @@ def test_templating_node__last_chat_message():
|
|
234
234
|
|
235
235
|
# THEN the output is the expected JSON
|
236
236
|
assert outputs.result == [ChatMessage(role="USER", text="Hello")]
|
237
|
+
|
238
|
+
|
239
|
+
def test_templating_node__function_call_value_input():
|
240
|
+
# GIVEN a templating node that receives a FunctionCallVellumValue
|
241
|
+
class FunctionCallTemplateNode(TemplatingNode[BaseState, FunctionCall]):
|
242
|
+
template = """{{ function_call }}"""
|
243
|
+
inputs = {
|
244
|
+
"function_call": FunctionCallVellumValue(
|
245
|
+
type="FUNCTION_CALL",
|
246
|
+
value=FunctionCall(name="test_function", arguments={"key": "value"}, id="test_id", state="FULFILLED"),
|
247
|
+
)
|
248
|
+
}
|
249
|
+
|
250
|
+
# WHEN the node is run
|
251
|
+
node = FunctionCallTemplateNode()
|
252
|
+
outputs = node.run()
|
253
|
+
|
254
|
+
# THEN the output is the expected function call
|
255
|
+
assert outputs.result == FunctionCall(
|
256
|
+
name="test_function", arguments={"key": "value"}, id="test_id", state="FULFILLED"
|
257
|
+
)
|
258
|
+
|
259
|
+
|
260
|
+
def test_templating_node__function_call_as_json():
|
261
|
+
# GIVEN a node that receives a FunctionCallVellumValue but outputs as Json
|
262
|
+
class JsonOutputNode(TemplatingNode[BaseState, Json]):
|
263
|
+
template = """{{ function_call }}"""
|
264
|
+
inputs = {
|
265
|
+
"function_call": FunctionCallVellumValue(
|
266
|
+
type="FUNCTION_CALL",
|
267
|
+
value=FunctionCall(name="test_function", arguments={"key": "value"}, id="test_id", state="FULFILLED"),
|
268
|
+
)
|
269
|
+
}
|
270
|
+
|
271
|
+
# WHEN the node is run
|
272
|
+
node = JsonOutputNode()
|
273
|
+
outputs = node.run()
|
274
|
+
|
275
|
+
# THEN we get just the FunctionCall data as JSON
|
276
|
+
assert outputs.result == {
|
277
|
+
"name": "test_function",
|
278
|
+
"arguments": {"key": "value"},
|
279
|
+
"id": "test_id",
|
280
|
+
"state": "FULFILLED",
|
281
|
+
}
|
282
|
+
|
283
|
+
# AND we can access fields directly
|
284
|
+
assert outputs.result["arguments"] == {"key": "value"}
|
285
|
+
assert outputs.result["name"] == "test_function"
|
vellum/workflows/nodes/utils.py
CHANGED
@@ -109,7 +109,11 @@ def parse_type_from_str(result_as_str: str, output_type: Any) -> Any:
|
|
109
109
|
|
110
110
|
if output_type is Json:
|
111
111
|
try:
|
112
|
-
|
112
|
+
data = json.loads(result_as_str)
|
113
|
+
# If we got a FunctionCallVellumValue, return just the value
|
114
|
+
if isinstance(data, dict) and data.get("type") == "FUNCTION_CALL" and "value" in data:
|
115
|
+
return data["value"]
|
116
|
+
return data
|
113
117
|
except json.JSONDecodeError:
|
114
118
|
raise ValueError("Invalid JSON format for result_as_str")
|
115
119
|
|
@@ -124,9 +128,16 @@ def parse_type_from_str(result_as_str: str, output_type: Any) -> Any:
|
|
124
128
|
if issubclass(output_type, BaseModel):
|
125
129
|
try:
|
126
130
|
data = json.loads(result_as_str)
|
131
|
+
# If we got a FunctionCallVellumValue extract FunctionCall,
|
132
|
+
if (
|
133
|
+
hasattr(output_type, "__name__")
|
134
|
+
and output_type.__name__ == "FunctionCall"
|
135
|
+
and isinstance(data, dict)
|
136
|
+
and "value" in data
|
137
|
+
):
|
138
|
+
data = data["value"]
|
139
|
+
return output_type.model_validate(data)
|
127
140
|
except json.JSONDecodeError:
|
128
141
|
raise ValueError("Invalid JSON format for result_as_str")
|
129
142
|
|
130
|
-
return output_type.model_validate(data)
|
131
|
-
|
132
143
|
raise ValueError(f"Unsupported output type: {output_type}")
|
@@ -328,11 +328,7 @@ class WorkflowRunner(Generic[StateType]):
|
|
328
328
|
node_definition=node.__class__,
|
329
329
|
error=e.error,
|
330
330
|
),
|
331
|
-
parent=
|
332
|
-
span_id=span_id,
|
333
|
-
workflow_definition=self.workflow.__class__,
|
334
|
-
parent=self._parent_context,
|
335
|
-
),
|
331
|
+
parent=parent_context,
|
336
332
|
)
|
337
333
|
)
|
338
334
|
except Exception as e:
|
@@ -89,9 +89,9 @@ vellum_ee/workflows/display/utils/expressions.py,sha256=9FpOslDI-RCR5m4TgAu9KCHh
|
|
89
89
|
vellum_ee/workflows/display/utils/vellum.py,sha256=UjK_RxnSEmlIu9klGCPWU5RAQBmgZ7cRbRdgxaTbubE,8081
|
90
90
|
vellum_ee/workflows/display/vellum.py,sha256=7mqQaKZPPrLMcXSAQkPIxCy5x8HkKs5PbCu3GRaC2o8,8507
|
91
91
|
vellum_ee/workflows/display/workflows/__init__.py,sha256=kapXsC67VJcgSuiBMa86FdePG5A9kMB5Pi4Uy1O2ob4,207
|
92
|
-
vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256=
|
92
|
+
vellum_ee/workflows/display/workflows/base_workflow_display.py,sha256=Z9s_rtqAH5IfBtXOw40gbiT0GZeN6JRdFwGgPT-DIYM,20143
|
93
93
|
vellum_ee/workflows/display/workflows/get_vellum_workflow_display_class.py,sha256=kp0u8LN_2IwshLrhMImhpZx1hRyAcD5gXY-kDuuaGMQ,1269
|
94
|
-
vellum_ee/workflows/display/workflows/tests/test_workflow_display.py,sha256=
|
94
|
+
vellum_ee/workflows/display/workflows/tests/test_workflow_display.py,sha256=STVSG0eL97mdnwBA5nOOgW8AuK8k-b8kWDyHKatNXIA,4259
|
95
95
|
vellum_ee/workflows/display/workflows/vellum_workflow_display.py,sha256=mbAzCpswOek34ITeTkesbVreCXpulj4NFjIg3RcdVZ8,18243
|
96
96
|
vellum_ee/workflows/server/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
97
97
|
vellum_ee/workflows/server/virtual_file_loader.py,sha256=X_DdNK7MfyOjKWekk6YQpOSCT6klKcdjT6nVJcBH1sM,1481
|
@@ -114,7 +114,7 @@ vellum_ee/workflows/tests/local_workflow/nodes/__init__.py,sha256=1F6jxUpSKfPXPj
|
|
114
114
|
vellum_ee/workflows/tests/local_workflow/nodes/final_output.py,sha256=ZX7zBv87zirg0w9VKUW3QVDSdBLDqcqAMZjCL_oWbpU,297
|
115
115
|
vellum_ee/workflows/tests/local_workflow/nodes/templating_node.py,sha256=NQwFN61QkHfI3Vssz-B0NKGfupK8PU0FDSAIAhYBLi0,325
|
116
116
|
vellum_ee/workflows/tests/local_workflow/workflow.py,sha256=A4qOzOPNwePYxWbcAgIPLsmrVS_aVEZEc-wULSv787Q,393
|
117
|
-
vellum_ee/workflows/tests/test_display_meta.py,sha256=
|
117
|
+
vellum_ee/workflows/tests/test_display_meta.py,sha256=xLQ7QtIXIiIm61pm2lyl588Ohzc3pjyq1nDp-qVu2Fs,2295
|
118
118
|
vellum_ee/workflows/tests/test_server.py,sha256=M6vvQ2hjIpDWtQdDM9EPbMvUrZ93niAuYnxMNJWOjPA,511
|
119
119
|
vellum_ee/workflows/tests/test_virtual_files.py,sha256=TJEcMR0v2S8CkloXNmCHA0QW0K6pYNGaIjraJz7sFvY,2762
|
120
120
|
vellum/__init__.py,sha256=a_aM1_A04XGma4MAIDNeBF9BKzWbiQaVVMRzImHuxjA,36438
|
@@ -122,7 +122,7 @@ vellum/client/README.md,sha256=JkCJjmMZl4jrPj46pkmL9dpK4gSzQQmP5I7z4aME4LY,4749
|
|
122
122
|
vellum/client/__init__.py,sha256=tKtdM1_GqmGq1gpi9ydWD_T-MM7fPn8QdHh8ww19cNI,117564
|
123
123
|
vellum/client/core/__init__.py,sha256=SQ85PF84B9MuKnBwHNHWemSGuy-g_515gFYNFhvEE0I,1438
|
124
124
|
vellum/client/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
|
125
|
-
vellum/client/core/client_wrapper.py,sha256=
|
125
|
+
vellum/client/core/client_wrapper.py,sha256=6EXwOd5Ka1mFWVlZmNuffO99dtW8DTAiRFes4vDlQFY,1869
|
126
126
|
vellum/client/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
|
127
127
|
vellum/client/core/file.py,sha256=X9IbmkZmB2bB_DpmZAO3crWdXagOakAyn6UCOCImCPg,2322
|
128
128
|
vellum/client/core/http_client.py,sha256=R0pQpCppnEtxccGvXl4uJ76s7ro_65Fo_erlNNLp_AI,19228
|
@@ -1287,7 +1287,7 @@ vellum/utils/templating/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
|
|
1287
1287
|
vellum/utils/templating/constants.py,sha256=8OHMO6WFAEimbIaiHc5gy6s91D7_KvW-vTlEMWwvl_M,711
|
1288
1288
|
vellum/utils/templating/custom_filters.py,sha256=XVHriwazejRZmxB_eg4xHgCxl7AiQQ2sx-hRLMmylfU,885
|
1289
1289
|
vellum/utils/templating/exceptions.py,sha256=cDp140PP4OnInW4qAvg3KqiSiF70C71UyEAKRBR1Abo,46
|
1290
|
-
vellum/utils/templating/render.py,sha256=
|
1290
|
+
vellum/utils/templating/render.py,sha256=P2t9qU4w_WdXAVLM5Nj3bc1-XlIKOkwK-czQ80pHBag,2172
|
1291
1291
|
vellum/utils/templating/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1292
1292
|
vellum/utils/templating/tests/test_custom_filters.py,sha256=mkJwc7t1gE13SKgPxhF-lN_m2XGCkphCB9Te81dGekI,532
|
1293
1293
|
vellum/utils/typing.py,sha256=wx_daFqD69cYkuJTVnvNrpjhqC3uuhbnyJ9_bIwC9OU,327
|
@@ -1315,7 +1315,7 @@ vellum/workflows/events/node.py,sha256=uHT6If0esgZ3nLjrjmUPTKf3qbjGhoV_x5YKpjDBD
|
|
1315
1315
|
vellum/workflows/events/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1316
1316
|
vellum/workflows/events/tests/test_event.py,sha256=uRfMwSOqU-ROeZKCEngGvvJYlOZuxBhnC3qH5AGi3fM,15399
|
1317
1317
|
vellum/workflows/events/types.py,sha256=cjRE8WL8tYCFradd9NOGl_H0mN3LiWWnA1uHmyT2Q0Q,3412
|
1318
|
-
vellum/workflows/events/workflow.py,sha256=
|
1318
|
+
vellum/workflows/events/workflow.py,sha256=sLO29djAeHGVd4hLhaNtOQ48uwUjfl-DotZQt06PxQA,6033
|
1319
1319
|
vellum/workflows/exceptions.py,sha256=NiBiR3ggfmPxBVqD-H1SqmjI-7mIn0EStSN1BqApvCM,1213
|
1320
1320
|
vellum/workflows/expressions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1321
1321
|
vellum/workflows/expressions/accessor.py,sha256=ItZF7fMLzVTqsdAiaXb5SiDupXmX0X9xbIus1W6hRds,1870
|
@@ -1381,8 +1381,8 @@ vellum/workflows/nodes/core/retry_node/node.py,sha256=Vt3fx4G-DRIb9a-IHIUfaAclgf
|
|
1381
1381
|
vellum/workflows/nodes/core/retry_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1382
1382
|
vellum/workflows/nodes/core/retry_node/tests/test_node.py,sha256=RM_OHwxrHwyxvlQQBJPqVBxpedFuWQ9h2-Xa3kP75sc,4399
|
1383
1383
|
vellum/workflows/nodes/core/templating_node/__init__.py,sha256=GmyuYo81_A1_Bz6id69ozVFS6FKiuDsZTiA3I6MaL2U,70
|
1384
|
-
vellum/workflows/nodes/core/templating_node/node.py,sha256
|
1385
|
-
vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py,sha256=
|
1384
|
+
vellum/workflows/nodes/core/templating_node/node.py,sha256=-JIqLUv6Xpx_LTVZt7whQ2X2VatgHDdTxjMrz64luEs,3721
|
1385
|
+
vellum/workflows/nodes/core/templating_node/tests/test_templating_node.py,sha256=ldnmSASx0TfAnT3ZvU0AXtN0diZGrfySiXipuJIIzWU,9055
|
1386
1386
|
vellum/workflows/nodes/core/try_node/__init__.py,sha256=JVD4DrldTIqFQQFrubs9KtWCCc0YCAc7Fzol5ZWIWeM,56
|
1387
1387
|
vellum/workflows/nodes/core/try_node/node.py,sha256=_0df2_6kim8pW4hB7IXUJOYS4fLduaeGDH4rRhYYvcg,4212
|
1388
1388
|
vellum/workflows/nodes/core/try_node/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -1448,7 +1448,7 @@ vellum/workflows/nodes/experimental/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQ
|
|
1448
1448
|
vellum/workflows/nodes/experimental/openai_chat_completion_node/__init__.py,sha256=lsyD9laR9p7kx5-BXGH2gUTM242UhKy8SMV0SR6S2iE,90
|
1449
1449
|
vellum/workflows/nodes/experimental/openai_chat_completion_node/node.py,sha256=1EGeiaT-Zoo6pttQFKKBcdf3dmhAbjKGaErYD5FFwlc,10185
|
1450
1450
|
vellum/workflows/nodes/mocks.py,sha256=gvM2tyoe-V84jFbFdhQsyGAPyQBzmjn_CkhT_yxccgY,499
|
1451
|
-
vellum/workflows/nodes/utils.py,sha256=
|
1451
|
+
vellum/workflows/nodes/utils.py,sha256=fq49n624n_nBMIFcc0JiNkHy3qna-bsA1HZRPa5AOJE,4918
|
1452
1452
|
vellum/workflows/outputs/__init__.py,sha256=AyZ4pRh_ACQIGvkf0byJO46EDnSix1ZCAXfvh-ms1QE,94
|
1453
1453
|
vellum/workflows/outputs/base.py,sha256=2MtTlyzePopMZDpBWQIV8HRV-km1-z0vI8Gm012q9OQ,8665
|
1454
1454
|
vellum/workflows/ports/__init__.py,sha256=bZuMt-R7z5bKwpu4uPW7LlJeePOQWmCcDSXe5frUY5g,101
|
@@ -1470,7 +1470,7 @@ vellum/workflows/references/workflow_input.py,sha256=86IuhlBz-9cGxeUzizyjdp482aj
|
|
1470
1470
|
vellum/workflows/resolvers/__init__.py,sha256=eH6hTvZO4IciDaf_cf7aM2vs-DkBDyJPycOQevJxQnI,82
|
1471
1471
|
vellum/workflows/resolvers/base.py,sha256=WHra9LRtlTuB1jmuNqkfVE2JUgB61Cyntn8f0b0WZg4,411
|
1472
1472
|
vellum/workflows/runner/__init__.py,sha256=i1iG5sAhtpdsrlvwgH6B-m49JsINkiWyPWs8vyT-bqM,72
|
1473
|
-
vellum/workflows/runner/runner.py,sha256=
|
1473
|
+
vellum/workflows/runner/runner.py,sha256=_p19T1woplSxZGabZuSUFBKSYBrXADrM7b_1YnWVN3g,31013
|
1474
1474
|
vellum/workflows/sandbox.py,sha256=GVJzVjMuYzOBnSrboB0_6MMRZWBluAyQ2o7syeaeBd0,2235
|
1475
1475
|
vellum/workflows/state/__init__.py,sha256=yUUdR-_Vl7UiixNDYQZ-GEM_kJI9dnOia75TtuNEsnE,60
|
1476
1476
|
vellum/workflows/state/base.py,sha256=Vkhneko3VlQrPsMLU1PYSzXU_W1u7_AraJsghiv5O-4,15512
|
@@ -1506,8 +1506,8 @@ vellum/workflows/workflows/event_filters.py,sha256=GSxIgwrX26a1Smfd-6yss2abGCnad
|
|
1506
1506
|
vellum/workflows/workflows/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
1507
1507
|
vellum/workflows/workflows/tests/test_base_workflow.py,sha256=NRteiICyJvDM5zrtUfq2fZoXcGQVaWC9xmNlLLVW0cU,7979
|
1508
1508
|
vellum/workflows/workflows/tests/test_context.py,sha256=VJBUcyWVtMa_lE5KxdhgMu0WYNYnUQUDvTF7qm89hJ0,2333
|
1509
|
-
vellum_ai-0.14.
|
1510
|
-
vellum_ai-0.14.
|
1511
|
-
vellum_ai-0.14.
|
1512
|
-
vellum_ai-0.14.
|
1513
|
-
vellum_ai-0.14.
|
1509
|
+
vellum_ai-0.14.10.dist-info/LICENSE,sha256=hOypcdt481qGNISA784bnAGWAE6tyIf9gc2E78mYC3E,1574
|
1510
|
+
vellum_ai-0.14.10.dist-info/METADATA,sha256=XNLaqqk85P8uRcr65-_IDfNPVi1dpNP9YvZgm43wAGs,5408
|
1511
|
+
vellum_ai-0.14.10.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
1512
|
+
vellum_ai-0.14.10.dist-info/entry_points.txt,sha256=HCH4yc_V3J_nDv3qJzZ_nYS8llCHZViCDP1ejgCc5Ak,42
|
1513
|
+
vellum_ai-0.14.10.dist-info/RECORD,,
|
@@ -9,7 +9,7 @@ from typing import Any, Dict, Generic, Iterator, List, Optional, Tuple, Type, Un
|
|
9
9
|
from vellum.workflows import BaseWorkflow
|
10
10
|
from vellum.workflows.descriptors.base import BaseDescriptor
|
11
11
|
from vellum.workflows.edges import Edge
|
12
|
-
from vellum.workflows.events.workflow import
|
12
|
+
from vellum.workflows.events.workflow import NodeEventDisplayContext, WorkflowEventDisplayContext
|
13
13
|
from vellum.workflows.expressions.coalesce_expression import CoalesceExpression
|
14
14
|
from vellum.workflows.nodes.bases import BaseNode
|
15
15
|
from vellum.workflows.nodes.utils import get_wrapped_node
|
@@ -34,7 +34,9 @@ from vellum_ee.workflows.display.base import (
|
|
34
34
|
from vellum_ee.workflows.display.nodes.base_node_vellum_display import BaseNodeVellumDisplay
|
35
35
|
from vellum_ee.workflows.display.nodes.get_node_display_class import get_node_display_class
|
36
36
|
from vellum_ee.workflows.display.nodes.types import NodeOutputDisplay, PortDisplay, PortDisplayOverrides
|
37
|
+
from vellum_ee.workflows.display.nodes.utils import raise_if_descriptor
|
37
38
|
from vellum_ee.workflows.display.types import NodeDisplayType, WorkflowDisplayContext
|
39
|
+
from vellum_ee.workflows.display.workflows.get_vellum_workflow_display_class import get_workflow_display
|
38
40
|
|
39
41
|
logger = logging.getLogger(__name__)
|
40
42
|
|
@@ -383,10 +385,15 @@ class BaseWorkflowDisplay(
|
|
383
385
|
except ModuleNotFoundError:
|
384
386
|
return None
|
385
387
|
|
386
|
-
|
387
|
-
if not isinstance(
|
388
|
+
workflow_display = display_class.WorkflowDisplay(workflow_class)
|
389
|
+
if not isinstance(workflow_display, BaseWorkflowDisplay):
|
388
390
|
return None
|
389
391
|
|
392
|
+
return workflow_display.get_event_display_context()
|
393
|
+
|
394
|
+
def get_event_display_context(self):
|
395
|
+
display_context = self.display_context
|
396
|
+
|
390
397
|
workflow_outputs = {
|
391
398
|
output.name: display_context.workflow_output_displays[output].id
|
392
399
|
for output in display_context.workflow_output_displays
|
@@ -398,27 +405,44 @@ class BaseWorkflowDisplay(
|
|
398
405
|
node_displays = {
|
399
406
|
str(node.__id__): display_context.node_displays[node] for node in display_context.node_displays
|
400
407
|
}
|
401
|
-
|
402
|
-
for
|
403
|
-
|
408
|
+
node_event_displays = {}
|
409
|
+
for node_id in node_displays:
|
410
|
+
current_node_display = node_displays[node_id]
|
404
411
|
input_display = {}
|
405
|
-
if isinstance(
|
406
|
-
input_display =
|
412
|
+
if isinstance(current_node_display, BaseNodeVellumDisplay):
|
413
|
+
input_display = current_node_display.node_input_ids_by_name
|
407
414
|
node_display_meta = {
|
408
|
-
output.name:
|
415
|
+
output.name: current_node_display.output_display[output].id
|
416
|
+
for output in current_node_display.output_display
|
409
417
|
}
|
410
|
-
port_display_meta = {
|
411
|
-
|
412
|
-
|
418
|
+
port_display_meta = {
|
419
|
+
port.name: current_node_display.port_displays[port].id for port in current_node_display.port_displays
|
420
|
+
}
|
421
|
+
node = current_node_display._node
|
422
|
+
subworkflow_display_context: Optional[WorkflowEventDisplayContext] = None
|
423
|
+
if hasattr(node, "subworkflow"):
|
424
|
+
# All nodes that have a subworkflow attribute are currently expected to call them `subworkflow`
|
425
|
+
# This will change if in the future we decide to support multiple subworkflows on a single node
|
426
|
+
subworkflow_attribute = raise_if_descriptor(getattr(node, "subworkflow"))
|
427
|
+
if issubclass(subworkflow_attribute, BaseWorkflow):
|
428
|
+
subworkflow_display = get_workflow_display(
|
429
|
+
base_display_class=display_context.workflow_display_class,
|
430
|
+
workflow_class=subworkflow_attribute,
|
431
|
+
parent_display_context=display_context,
|
432
|
+
)
|
433
|
+
subworkflow_display_context = subworkflow_display.get_event_display_context()
|
434
|
+
|
435
|
+
node_event_displays[node_id] = NodeEventDisplayContext(
|
413
436
|
input_display=input_display,
|
414
437
|
output_display=node_display_meta,
|
415
438
|
port_display=port_display_meta,
|
439
|
+
subworkflow_display=subworkflow_display_context,
|
416
440
|
)
|
417
441
|
|
418
442
|
display_meta = WorkflowEventDisplayContext(
|
419
443
|
workflow_outputs=workflow_outputs,
|
420
444
|
workflow_inputs=workflow_inputs,
|
421
|
-
node_displays=
|
445
|
+
node_displays=node_event_displays,
|
422
446
|
)
|
423
447
|
return display_meta
|
424
448
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import pytest
|
2
2
|
|
3
3
|
from vellum.workflows.nodes.bases.base import BaseNode
|
4
|
+
from vellum.workflows.nodes.core.inline_subworkflow_node.node import InlineSubworkflowNode
|
4
5
|
from vellum.workflows.workflows.base import BaseWorkflow
|
5
6
|
from vellum_ee.workflows.display.nodes import BaseNodeDisplay
|
6
7
|
from vellum_ee.workflows.display.vellum import NodeDisplayData, NodeDisplayPosition
|
@@ -92,3 +93,29 @@ def test_serialize_workflow__node_display_class_not_registered():
|
|
92
93
|
|
93
94
|
# THEN it should should succeed
|
94
95
|
assert data is not None
|
96
|
+
|
97
|
+
|
98
|
+
def test_get_event_display_context__node_display_to_include_subworkflow_display():
|
99
|
+
# GIVEN a simple workflow
|
100
|
+
class InnerNode(BaseNode):
|
101
|
+
pass
|
102
|
+
|
103
|
+
class Subworkflow(BaseWorkflow):
|
104
|
+
graph = InnerNode
|
105
|
+
|
106
|
+
# AND a workflow that includes the subworkflow
|
107
|
+
class SubworkflowNode(InlineSubworkflowNode):
|
108
|
+
subworkflow = Subworkflow
|
109
|
+
|
110
|
+
class MyWorkflow(BaseWorkflow):
|
111
|
+
graph = SubworkflowNode
|
112
|
+
|
113
|
+
# WHEN we gather the event display context
|
114
|
+
display_context = VellumWorkflowDisplay(MyWorkflow).get_event_display_context()
|
115
|
+
|
116
|
+
# THEN the subworkflow display should be included
|
117
|
+
assert str(SubworkflowNode.__id__) in display_context.node_displays
|
118
|
+
node_event_display = display_context.node_displays[str(SubworkflowNode.__id__)]
|
119
|
+
|
120
|
+
assert node_event_display.subworkflow_display is not None
|
121
|
+
assert str(InnerNode.__id__) in node_event_display.subworkflow_display.node_displays
|
@@ -40,11 +40,13 @@ def test_base_class_dynamic_import(files):
|
|
40
40
|
},
|
41
41
|
"output_display": {"result": UUID("423bc529-1a1a-4f72-af4d-cbdb5f0a5929")},
|
42
42
|
"port_display": {"default": UUID("afda9a19-0618-42e1-9b63-5d0db2a88f62")},
|
43
|
+
"subworkflow_display": None,
|
43
44
|
},
|
44
45
|
"f3ef4b2b-fec9-4026-9cc6-e5eac295307f": {
|
45
46
|
"input_display": {"node_input": UUID("fe6cba85-2423-4b5e-8f85-06311a8be5fb")},
|
46
47
|
"output_display": {"value": UUID("5469b810-6ea6-4362-9e79-e360d44a1405")},
|
47
48
|
"port_display": {},
|
49
|
+
"subworkflow_display": None,
|
48
50
|
},
|
49
51
|
},
|
50
52
|
"workflow_inputs": {"input_value": UUID("2268a996-bd17-4832-b3ff-f5662d54b306")},
|
File without changes
|
File without changes
|
File without changes
|