vellum-ai 1.7.4__py3-none-any.whl → 1.7.6__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/__init__.py +2 -0
- vellum/client/core/client_wrapper.py +2 -2
- vellum/client/reference.md +95 -0
- vellum/client/resources/workflow_deployments/client.py +111 -0
- vellum/client/resources/workflow_deployments/raw_client.py +121 -0
- vellum/client/types/__init__.py +2 -0
- vellum/client/types/paginated_workflow_deployment_release_list.py +30 -0
- vellum/client/types/vellum_error_code_enum.py +2 -0
- vellum/client/types/vellum_sdk_error_code_enum.py +2 -0
- vellum/client/types/workflow_execution_event_error_code.py +2 -0
- vellum/types/paginated_workflow_deployment_release_list.py +3 -0
- vellum/workflows/edges/__init__.py +2 -0
- vellum/workflows/edges/trigger_edge.py +67 -0
- vellum/workflows/events/tests/test_event.py +40 -0
- vellum/workflows/events/workflow.py +15 -3
- vellum/workflows/graph/graph.py +93 -0
- vellum/workflows/graph/tests/test_graph.py +167 -0
- vellum/workflows/nodes/bases/base.py +28 -9
- vellum/workflows/nodes/displayable/search_node/node.py +2 -1
- vellum/workflows/nodes/displayable/search_node/tests/test_node.py +14 -0
- vellum/workflows/nodes/displayable/subworkflow_deployment_node/node.py +7 -1
- vellum/workflows/nodes/displayable/subworkflow_deployment_node/tests/test_node.py +1 -1
- vellum/workflows/nodes/displayable/tool_calling_node/node.py +1 -1
- vellum/workflows/nodes/displayable/tool_calling_node/tests/test_node.py +54 -0
- vellum/workflows/nodes/displayable/tool_calling_node/utils.py +27 -25
- vellum/workflows/ports/port.py +11 -0
- vellum/workflows/runner/runner.py +30 -40
- vellum/workflows/triggers/__init__.py +5 -0
- vellum/workflows/triggers/base.py +125 -0
- vellum/workflows/triggers/integration.py +62 -0
- vellum/workflows/triggers/manual.py +37 -0
- vellum/workflows/triggers/tests/__init__.py +1 -0
- vellum/workflows/triggers/tests/test_integration.py +102 -0
- vellum/workflows/workflows/base.py +26 -12
- {vellum_ai-1.7.4.dist-info → vellum_ai-1.7.6.dist-info}/METADATA +1 -1
- {vellum_ai-1.7.4.dist-info → vellum_ai-1.7.6.dist-info}/RECORD +48 -38
- vellum_cli/push.py +1 -5
- vellum_cli/tests/test_push.py +86 -0
- vellum_ee/assets/node-definitions.json +1 -1
- vellum_ee/workflows/display/base.py +26 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_serialization.py +1 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_serialization.py +1 -1
- vellum_ee/workflows/display/tests/workflow_serialization/test_manual_trigger_serialization.py +110 -0
- vellum_ee/workflows/display/workflows/base_workflow_display.py +72 -10
- vellum_ee/workflows/tests/test_server.py +40 -1
- {vellum_ai-1.7.4.dist-info → vellum_ai-1.7.6.dist-info}/LICENSE +0 -0
- {vellum_ai-1.7.4.dist-info → vellum_ai-1.7.6.dist-info}/WHEEL +0 -0
- {vellum_ai-1.7.4.dist-info → vellum_ai-1.7.6.dist-info}/entry_points.txt +0 -0
@@ -37,6 +37,7 @@ from vellum_ee.workflows.display.base import (
|
|
37
37
|
WorkflowInputsDisplay,
|
38
38
|
WorkflowMetaDisplay,
|
39
39
|
WorkflowOutputDisplay,
|
40
|
+
get_trigger_type_mapping,
|
40
41
|
)
|
41
42
|
from vellum_ee.workflows.display.editor.types import NodeDisplayData, NodeDisplayPosition
|
42
43
|
from vellum_ee.workflows.display.nodes.base_node_display import BaseNodeDisplay
|
@@ -408,22 +409,83 @@ class BaseWorkflowDisplay(Generic[WorkflowType]):
|
|
408
409
|
except Exception as e:
|
409
410
|
self.display_context.add_error(e)
|
410
411
|
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
"
|
412
|
+
# Serialize workflow-level trigger if present
|
413
|
+
triggers: Optional[JsonArray] = self._serialize_workflow_trigger()
|
414
|
+
|
415
|
+
workflow_raw_data: JsonObject = {
|
416
|
+
"nodes": cast(JsonArray, nodes_dict_list),
|
417
|
+
"edges": edges,
|
418
|
+
"display_data": self.display_context.workflow_display.display_data.dict(),
|
419
|
+
"definition": {
|
420
|
+
"name": self._workflow.__name__,
|
421
|
+
"module": cast(JsonArray, self._workflow.__module__.split(".")),
|
421
422
|
},
|
423
|
+
"output_values": output_values,
|
424
|
+
}
|
425
|
+
|
426
|
+
result: JsonObject = {
|
427
|
+
"workflow_raw_data": workflow_raw_data,
|
422
428
|
"input_variables": input_variables,
|
423
429
|
"state_variables": state_variables,
|
424
430
|
"output_variables": output_variables,
|
425
431
|
}
|
426
432
|
|
433
|
+
if triggers is not None:
|
434
|
+
result["triggers"] = triggers
|
435
|
+
|
436
|
+
return result
|
437
|
+
|
438
|
+
def _serialize_workflow_trigger(self) -> Optional[JsonArray]:
|
439
|
+
"""
|
440
|
+
Serialize workflow-level trigger information.
|
441
|
+
|
442
|
+
Returns:
|
443
|
+
JsonArray with trigger data if a trigger is present, None otherwise.
|
444
|
+
Each trigger in the array has: id (UUID), type (str), attributes (list)
|
445
|
+
"""
|
446
|
+
# Get all trigger edges from the workflow's subgraphs
|
447
|
+
trigger_edges = []
|
448
|
+
for subgraph in self._workflow.get_subgraphs():
|
449
|
+
trigger_edges.extend(list(subgraph.trigger_edges))
|
450
|
+
|
451
|
+
if not trigger_edges:
|
452
|
+
# No workflow-level trigger defined
|
453
|
+
return None
|
454
|
+
|
455
|
+
# Get the trigger class from the first edge
|
456
|
+
trigger_class = trigger_edges[0].trigger_class
|
457
|
+
|
458
|
+
# Validate that all trigger edges use the same trigger type
|
459
|
+
trigger_type_mapping = get_trigger_type_mapping()
|
460
|
+
for edge in trigger_edges:
|
461
|
+
if edge.trigger_class != trigger_class:
|
462
|
+
raise ValueError(
|
463
|
+
f"Mixed trigger types not supported. Found {trigger_class.__name__} and "
|
464
|
+
f"{edge.trigger_class.__name__} in the same workflow."
|
465
|
+
)
|
466
|
+
|
467
|
+
# Get the trigger type from the mapping
|
468
|
+
trigger_type = trigger_type_mapping.get(trigger_class)
|
469
|
+
if trigger_type is None:
|
470
|
+
raise ValueError(
|
471
|
+
f"Unknown trigger type: {trigger_class.__name__}. "
|
472
|
+
f"Please add it to the trigger type mapping in get_trigger_type_mapping()."
|
473
|
+
)
|
474
|
+
|
475
|
+
# Return as a list with a single trigger object matching Django schema
|
476
|
+
trigger_id = uuid4_from_hash(f"{trigger_class.__module__} | {trigger_class.__qualname__}")
|
477
|
+
|
478
|
+
return cast(
|
479
|
+
JsonArray,
|
480
|
+
[
|
481
|
+
{
|
482
|
+
"id": str(trigger_id),
|
483
|
+
"type": trigger_type.value,
|
484
|
+
"attributes": [],
|
485
|
+
}
|
486
|
+
],
|
487
|
+
)
|
488
|
+
|
427
489
|
def _serialize_edge_display_data(self, edge_display: EdgeDisplay) -> Optional[JsonObject]:
|
428
490
|
"""Serialize edge display data, returning None if no display data is present."""
|
429
491
|
if edge_display.z_index is not None:
|
@@ -536,10 +536,49 @@ class BrokenNode(BaseNode) # Missing colon
|
|
536
536
|
|
537
537
|
# AND the error message should be user-friendly
|
538
538
|
error_message = str(exc_info.value)
|
539
|
-
assert "
|
539
|
+
assert "Syntax Error raised while loading Workflow:" in error_message
|
540
540
|
assert "invalid syntax" in error_message or "expected ':'" in error_message
|
541
541
|
|
542
542
|
|
543
|
+
def test_load_from_module__name_error_in_node_file():
|
544
|
+
"""
|
545
|
+
Tests that a NameError in a node file raises WorkflowInitializationException with user-facing message.
|
546
|
+
"""
|
547
|
+
# GIVEN a workflow module with a node file containing a NameError (undefined class reference)
|
548
|
+
files = {
|
549
|
+
"__init__.py": "",
|
550
|
+
"workflow.py": """\
|
551
|
+
from vellum.workflows import BaseWorkflow
|
552
|
+
from .nodes.broken_node import BrokenNode
|
553
|
+
|
554
|
+
class Workflow(BaseWorkflow):
|
555
|
+
graph = BrokenNode
|
556
|
+
""",
|
557
|
+
"nodes/__init__.py": "",
|
558
|
+
"nodes/broken_node.py": """\
|
559
|
+
from vellum.workflows.nodes import BaseNode
|
560
|
+
|
561
|
+
class BrokenNode(BaseNode):
|
562
|
+
some_attribute = UndefinedClass()
|
563
|
+
""",
|
564
|
+
}
|
565
|
+
|
566
|
+
namespace = str(uuid4())
|
567
|
+
|
568
|
+
# AND the virtual file loader is registered
|
569
|
+
sys.meta_path.append(VirtualFileFinder(files, namespace))
|
570
|
+
|
571
|
+
# WHEN we attempt to load the workflow
|
572
|
+
# THEN it should raise WorkflowInitializationException
|
573
|
+
with pytest.raises(WorkflowInitializationException) as exc_info:
|
574
|
+
BaseWorkflow.load_from_module(namespace)
|
575
|
+
|
576
|
+
# AND the error message should be user-friendly
|
577
|
+
error_message = str(exc_info.value)
|
578
|
+
assert "Invalid variable reference:" in error_message
|
579
|
+
assert "UndefinedClass" in error_message or "not defined" in error_message
|
580
|
+
|
581
|
+
|
543
582
|
def test_serialize_module__tool_calling_node_with_single_tool():
|
544
583
|
"""Test that serialize_module works with a tool calling node that has a single tool."""
|
545
584
|
|
File without changes
|
File without changes
|
File without changes
|