vellum-workflow-server 0.14.71.post5__tar.gz → 0.14.72.post1__tar.gz

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.

Potentially problematic release.


This version of vellum-workflow-server might be problematic. Click here for more details.

Files changed (31) hide show
  1. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/PKG-INFO +2 -2
  2. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/pyproject.toml +2 -2
  3. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/api/tests/test_workflow_view.py +122 -19
  4. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/api/workflow_view.py +17 -4
  5. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/README.md +0 -0
  6. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/__init__.py +0 -0
  7. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/api/__init__.py +0 -0
  8. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/api/auth_middleware.py +0 -0
  9. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/api/healthz_view.py +0 -0
  10. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/api/tests/__init__.py +0 -0
  11. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/api/tests/test_input_display_mapping.py +0 -0
  12. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/api/tests/test_workflow_view_stream_workflow_route.py +0 -0
  13. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/code_exec_runner.py +0 -0
  14. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/config.py +0 -0
  15. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/core/__init__.py +0 -0
  16. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/core/cancel_workflow.py +0 -0
  17. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/core/events.py +0 -0
  18. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/core/executor.py +0 -0
  19. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/core/workflow_executor_context.py +0 -0
  20. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/server.py +0 -0
  21. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/start.py +0 -0
  22. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/utils/__init__.py +0 -0
  23. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/utils/exit_handler.py +0 -0
  24. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/utils/log_proxy.py +0 -0
  25. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/utils/oom_killer.py +0 -0
  26. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/utils/sentry.py +0 -0
  27. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/utils/system_utils.py +0 -0
  28. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/utils/tests/__init__.py +0 -0
  29. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/utils/tests/test_system_utils.py +0 -0
  30. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/utils/tests/test_utils.py +0 -0
  31. {vellum_workflow_server-0.14.71.post5 → vellum_workflow_server-0.14.72.post1}/src/workflow_server/utils/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: vellum-workflow-server
3
- Version: 0.14.71.post5
3
+ Version: 0.14.72.post1
4
4
  Summary:
5
5
  License: AGPL
6
6
  Requires-Python: >=3.9.0,<4
@@ -28,7 +28,7 @@ Requires-Dist: pebble (==5.0.7)
28
28
  Requires-Dist: pyjwt (==2.10.0)
29
29
  Requires-Dist: python-dotenv (==1.0.1)
30
30
  Requires-Dist: sentry-sdk[flask] (==2.20.0)
31
- Requires-Dist: vellum-ai (==0.14.71)
31
+ Requires-Dist: vellum-ai (==0.14.72)
32
32
  Description-Content-Type: text/markdown
33
33
 
34
34
  # Vellum Workflow Runner Server
@@ -3,7 +3,7 @@ name = "vellum-workflow-server"
3
3
 
4
4
  [tool.poetry]
5
5
  name = "vellum-workflow-server"
6
- version = "0.14.71.post5"
6
+ version = "0.14.72.post1"
7
7
  description = ""
8
8
  readme = "README.md"
9
9
  authors = []
@@ -44,7 +44,7 @@ flask = "2.3.3"
44
44
  orderly-set = "5.2.2"
45
45
  pebble = "5.0.7"
46
46
  gunicorn = "23.0.0"
47
- vellum-ai = "0.14.71"
47
+ vellum-ai = "0.14.72"
48
48
  python-dotenv = "1.0.1"
49
49
  sentry-sdk = {extras = ["flask"], version = "2.20.0"}
50
50
 
@@ -27,10 +27,7 @@ def test_version_route__with_single_node_file(tmp_path):
27
27
  from vellum.workflows.nodes import BaseNode
28
28
 
29
29
  class TestNode(BaseNode):
30
- \"""A test node for processing data.
31
-
32
- This is a detailed description of what the node does.
33
- \"""
30
+ \"""A test node for processing data.\"""
34
31
  """
35
32
  )
36
33
 
@@ -50,11 +47,26 @@ class TestNode(BaseNode):
50
47
  # AND the node should have the correct metadata
51
48
  node = nodes[0]
52
49
  assert UUID(node["id"])
53
- assert node["module"] == ["vellum_custom_nodes"]
50
+ assert node["module"] == ["vellum_custom_nodes", "test_node"]
54
51
  assert node["name"] == "TestNode"
55
52
  assert node["label"] == "Test Node"
56
53
  assert "A test node for processing data." in node["description"]
57
- assert "This is a detailed description" in node["description"]
54
+ assert node["exec_config"] == {
55
+ "adornments": None,
56
+ "attributes": [],
57
+ "base": {"module": ["vellum", "workflows", "nodes", "bases", "base"], "name": "BaseNode"},
58
+ "definition": {"module": ["vellum_custom_nodes", "test_node"], "name": "TestNode"},
59
+ "display_data": {
60
+ "comment": {"value": "A test node for processing data."},
61
+ "position": {"x": 0.0, "y": 0.0},
62
+ },
63
+ "id": "7a8b251d-f5ca-462a-b293-071d219460fb",
64
+ "label": "TestNode",
65
+ "outputs": [],
66
+ "ports": [{"id": "a3a0eefd-45d0-4f13-8c58-a836a9f7f9ed", "name": "default", "type": "DEFAULT"}],
67
+ "trigger": {"id": "a022e36c-9852-4772-9be3-3c6c147fd811", "merge_behavior": "AWAIT_ATTRIBUTES"},
68
+ "type": "GENERIC",
69
+ }
58
70
 
59
71
 
60
72
  def test_version_route__with_nodes_in_multiple_files(tmp_path):
@@ -102,14 +114,40 @@ class SomeOtherNode(BaseNode):
102
114
  assert some_node["label"] == "Some Node"
103
115
  assert some_node["description"] == "This is Some Node."
104
116
  assert UUID(some_node["id"])
105
- assert some_node["module"] == ["vellum_custom_nodes"]
117
+ assert some_node["module"] == ["vellum_custom_nodes", "first_node"]
118
+ assert some_node["exec_config"] == {
119
+ "adornments": None,
120
+ "attributes": [],
121
+ "base": {"module": ["vellum", "workflows", "nodes", "bases", "base"], "name": "BaseNode"},
122
+ "definition": {"module": ["vellum_custom_nodes", "first_node"], "name": "SomeNode"},
123
+ "display_data": {"comment": {"value": "This is Some Node."}, "position": {"x": 0.0, "y": 0.0}},
124
+ "id": "1e559c2e-db82-41f0-9ceb-5e89b0c5a0a3",
125
+ "label": "SomeNode",
126
+ "outputs": [],
127
+ "ports": [{"id": "48e39e97-5fd4-471e-b4f2-51d3baf06456", "name": "default", "type": "DEFAULT"}],
128
+ "trigger": {"id": "e3381fb7-61fc-4c46-ae8e-51fc463b6a59", "merge_behavior": "AWAIT_ATTRIBUTES"},
129
+ "type": "GENERIC",
130
+ }
106
131
 
107
132
  # AND the second node should have correct metadata
108
133
  some_other_node = nodes[1]
109
134
  assert some_other_node["label"] == "Some Other Node"
110
135
  assert some_other_node["description"] == "This is Some Other Node."
111
136
  assert UUID(some_other_node["id"])
112
- assert some_other_node["module"] == ["vellum_custom_nodes"]
137
+ assert some_other_node["module"] == ["vellum_custom_nodes", "second_node"]
138
+ assert some_other_node["exec_config"] == {
139
+ "adornments": None,
140
+ "attributes": [],
141
+ "base": {"module": ["vellum", "workflows", "nodes", "bases", "base"], "name": "BaseNode"},
142
+ "definition": {"module": ["vellum_custom_nodes", "second_node"], "name": "SomeOtherNode"},
143
+ "display_data": {"comment": {"value": "This is Some Other Node."}, "position": {"x": 0.0, "y": 0.0}},
144
+ "id": "7aee541b-b245-4c8a-9137-3e4631d5100c",
145
+ "label": "SomeOtherNode",
146
+ "outputs": [],
147
+ "ports": [{"id": "fb66b46a-d970-4bc9-83ea-70c154c57ddd", "name": "default", "type": "DEFAULT"}],
148
+ "trigger": {"id": "13fa2714-20b3-4bc3-ab79-621a188e3bfa", "merge_behavior": "AWAIT_ATTRIBUTES"},
149
+ "type": "GENERIC",
150
+ }
113
151
 
114
152
 
115
153
  def test_version_route__no_custom_nodes_dir(tmp_path):
@@ -164,6 +202,37 @@ class HelperClass:
164
202
  node_names = {node["name"] for node in nodes}
165
203
  assert node_names == {"ProcessingNode", "TransformationNode"}
166
204
 
205
+ # Find and assert each node individually
206
+ processing_node = next(node for node in nodes if node["name"] == "ProcessingNode")
207
+ assert processing_node["exec_config"] == {
208
+ "adornments": None,
209
+ "attributes": [],
210
+ "base": {"module": ["vellum", "workflows", "nodes", "bases", "base"], "name": "BaseNode"},
211
+ "definition": {"module": ["vellum_custom_nodes", "multiple_nodes"], "name": "ProcessingNode"},
212
+ "display_data": {"comment": {"value": "Processes input data."}, "position": {"x": 0.0, "y": 0.0}},
213
+ "id": "f92c09f0-0434-46cb-829d-a73f801d6343",
214
+ "label": "ProcessingNode",
215
+ "outputs": [],
216
+ "ports": [{"id": "abaa2984-b312-4491-b069-e689759f72c8", "name": "default", "type": "DEFAULT"}],
217
+ "trigger": {"id": "35378c2b-f089-44af-ac37-efe4ea42c817", "merge_behavior": "AWAIT_ATTRIBUTES"},
218
+ "type": "GENERIC",
219
+ }
220
+
221
+ transformation_node = next(node for node in nodes if node["name"] == "TransformationNode")
222
+ assert transformation_node["exec_config"] == {
223
+ "adornments": None,
224
+ "attributes": [],
225
+ "base": {"module": ["vellum", "workflows", "nodes", "bases", "base"], "name": "BaseNode"},
226
+ "definition": {"module": ["vellum_custom_nodes", "multiple_nodes"], "name": "TransformationNode"},
227
+ "display_data": {"comment": {"value": "Transforms data format."}, "position": {"x": 0.0, "y": 0.0}},
228
+ "id": "09ca32f7-c8f2-4469-97e5-1f288f85127a",
229
+ "label": "TransformationNode",
230
+ "outputs": [],
231
+ "ports": [{"id": "88778117-fbfc-4b44-964b-5a4994aa2f24", "name": "default", "type": "DEFAULT"}],
232
+ "trigger": {"id": "5d096263-7fbf-490a-83b7-e441852b5fb6", "merge_behavior": "AWAIT_ATTRIBUTES"},
233
+ "type": "GENERIC",
234
+ }
235
+
167
236
 
168
237
  def test_version_route__with_invalid_node_file(tmp_path, caplog):
169
238
  caplog.set_level(logging.WARNING)
@@ -212,7 +281,20 @@ class BrokenNode(BaseNode)
212
281
  assert valid_node["label"] == "Some Node"
213
282
  assert valid_node["description"] == "This is Some Node."
214
283
  assert UUID(valid_node["id"])
215
- assert valid_node["module"] == ["vellum_custom_nodes"]
284
+ assert valid_node["module"] == ["vellum_custom_nodes", "valid_node"]
285
+ assert valid_node["exec_config"] == {
286
+ "adornments": None,
287
+ "attributes": [],
288
+ "base": {"module": ["vellum", "workflows", "nodes", "bases", "base"], "name": "BaseNode"},
289
+ "definition": {"module": ["vellum_custom_nodes", "valid_node"], "name": "SomeNode"},
290
+ "display_data": {"comment": {"value": "This is Some Node."}, "position": {"x": 0.0, "y": 0.0}},
291
+ "id": "1e559c2e-db82-41f0-9ceb-5e89b0c5a0a3",
292
+ "label": "SomeNode",
293
+ "outputs": [],
294
+ "ports": [{"id": "48e39e97-5fd4-471e-b4f2-51d3baf06456", "name": "default", "type": "DEFAULT"}],
295
+ "trigger": {"id": "e3381fb7-61fc-4c46-ae8e-51fc463b6a59", "merge_behavior": "AWAIT_ATTRIBUTES"},
296
+ "type": "GENERIC",
297
+ }
216
298
 
217
299
  # AND the error should be logged with full traceback
218
300
  assert len(caplog.records) > 0
@@ -221,7 +303,7 @@ class BrokenNode(BaseNode)
221
303
  assert "invalid_node.py, line 4" in error_message
222
304
 
223
305
 
224
- def test_version_route__with_inputs(tmp_path):
306
+ def test_version_route__with_attributes(tmp_path):
225
307
  # GIVEN a temporary custom_nodes directory
226
308
  custom_nodes_dir = tmp_path / "vellum_custom_nodes"
227
309
  custom_nodes_dir.mkdir()
@@ -230,19 +312,13 @@ def test_version_route__with_inputs(tmp_path):
230
312
  node_file = custom_nodes_dir / "addition_node.py"
231
313
  node_file.write_text(
232
314
  """
233
- from vellum.workflows.inputs import BaseInputs
234
315
  from vellum.workflows.nodes import BaseNode
235
316
 
236
317
 
237
- class Inputs(BaseInputs):
238
- arg1: int
239
- arg2: int
240
-
241
-
242
318
  class MyAdditionNode(BaseNode):
243
319
  \"\"\"Custom node that performs simple addition.\"\"\"
244
- arg1: int = Inputs.arg1
245
- arg2: int = Inputs.arg2
320
+ arg1: int
321
+ arg2: int
246
322
 
247
323
  class Outputs(BaseNode.Outputs):
248
324
  result: int
@@ -271,5 +347,32 @@ class MyAdditionNode(BaseNode):
271
347
  assert node["label"] == "My Addition Node"
272
348
  assert node["description"] == "Custom node that performs simple addition."
273
349
  assert UUID(node["id"])
274
- assert node["module"] == ["vellum_custom_nodes"]
350
+ assert node["module"] == ["vellum_custom_nodes", "addition_node"]
275
351
  assert node["name"] == "MyAdditionNode"
352
+ assert node["exec_config"] == {
353
+ "adornments": None,
354
+ "attributes": [
355
+ {
356
+ "id": "aed3bcbb-d243-4a77-bb5e-409e9a28e868",
357
+ "name": "arg1",
358
+ "value": {"type": "CONSTANT_VALUE", "value": {"type": "JSON", "value": None}},
359
+ },
360
+ {
361
+ "id": "9225d225-a41b-4642-8964-f28f58dcf4bf",
362
+ "name": "arg2",
363
+ "value": {"type": "CONSTANT_VALUE", "value": {"type": "JSON", "value": None}},
364
+ },
365
+ ],
366
+ "base": {"module": ["vellum", "workflows", "nodes", "bases", "base"], "name": "BaseNode"},
367
+ "definition": {"module": ["vellum_custom_nodes", "addition_node"], "name": "MyAdditionNode"},
368
+ "display_data": {
369
+ "comment": {"value": "Custom node that performs simple addition."},
370
+ "position": {"x": 0.0, "y": 0.0},
371
+ },
372
+ "id": "195cd69d-3d2d-41e4-a432-16c433cb8d34",
373
+ "label": "MyAdditionNode",
374
+ "outputs": [{"id": "3d8e40cb-2aa8-44bd-ae6a-708a9fbc4779", "name": "result", "type": "NUMBER", "value": None}],
375
+ "ports": [{"id": "9a9e4ef6-febf-4093-a515-217bbb1373db", "name": "default", "type": "DEFAULT"}],
376
+ "trigger": {"id": "a5298668-d808-4a45-a62e-790943948e8a", "merge_behavior": "AWAIT_ATTRIBUTES"},
377
+ "type": "GENERIC",
378
+ }
@@ -11,10 +11,12 @@ import sys
11
11
  import time
12
12
  import traceback
13
13
  from uuid import uuid4
14
- from typing import Generator, Iterator, Union
14
+ from typing import Any, Dict, Generator, Iterator, Union, cast
15
15
 
16
16
  from flask import Blueprint, Response, current_app as app, request, stream_with_context
17
17
  from pydantic import ValidationError
18
+ from vellum_ee.workflows.display.nodes.get_node_display_class import get_node_display_class
19
+ from vellum_ee.workflows.display.types import WorkflowDisplayContext
18
20
 
19
21
  from vellum.workflows.nodes import BaseNode
20
22
  from vellum.workflows.utils.names import pascal_to_title_case
@@ -371,16 +373,27 @@ def get_version_route() -> tuple[dict, int]:
371
373
  for _, name, _ in pkgutil.iter_modules([custom_nodes_path]):
372
374
  try:
373
375
  module = importlib.import_module(f"{CUSTOM_NODES_DIRECTORY}.{name}")
374
- for label, obj in inspect.getmembers(module):
376
+ for _, obj in inspect.getmembers(module):
375
377
  # Look for classes that inherit from BaseNode
376
378
  if inspect.isclass(obj) and obj != BaseNode and issubclass(obj, BaseNode):
379
+ node_display_class = get_node_display_class(obj)
380
+ exec_config_raw = node_display_class().serialize(WorkflowDisplayContext())
381
+ exec_config = cast(Dict[str, Any], exec_config_raw)
382
+ module = exec_config["definition"]["module"]
383
+ label = exec_config["label"]
384
+ description = (
385
+ exec_config["display_data"]["comment"]["value"]
386
+ if "comment" in exec_config["display_data"]
387
+ else ""
388
+ )
377
389
  nodes.append(
378
390
  {
379
391
  "id": str(uuid4()),
380
- "module": CUSTOM_NODES_DIRECTORY.split("/"),
392
+ "module": module,
381
393
  "name": obj.__name__,
382
394
  "label": pascal_to_title_case(label),
383
- "description": inspect.getdoc(obj) or "",
395
+ "description": description,
396
+ "exec_config": exec_config,
384
397
  }
385
398
  )
386
399
  except Exception as e: