vellum-ai 1.7.4__py3-none-any.whl → 1.7.5__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.
Files changed (36) hide show
  1. vellum/__init__.py +2 -0
  2. vellum/client/core/client_wrapper.py +2 -2
  3. vellum/client/reference.md +95 -0
  4. vellum/client/resources/workflow_deployments/client.py +111 -0
  5. vellum/client/resources/workflow_deployments/raw_client.py +121 -0
  6. vellum/client/types/__init__.py +2 -0
  7. vellum/client/types/paginated_workflow_deployment_release_list.py +30 -0
  8. vellum/client/types/vellum_error_code_enum.py +2 -0
  9. vellum/client/types/vellum_sdk_error_code_enum.py +2 -0
  10. vellum/client/types/workflow_execution_event_error_code.py +2 -0
  11. vellum/types/paginated_workflow_deployment_release_list.py +3 -0
  12. vellum/workflows/edges/__init__.py +2 -0
  13. vellum/workflows/edges/trigger_edge.py +67 -0
  14. vellum/workflows/events/tests/test_event.py +40 -0
  15. vellum/workflows/events/workflow.py +15 -3
  16. vellum/workflows/graph/graph.py +93 -0
  17. vellum/workflows/graph/tests/test_graph.py +167 -0
  18. vellum/workflows/nodes/displayable/tool_calling_node/node.py +1 -1
  19. vellum/workflows/nodes/displayable/tool_calling_node/utils.py +1 -1
  20. vellum/workflows/ports/port.py +11 -0
  21. vellum/workflows/runner/runner.py +5 -3
  22. vellum/workflows/triggers/__init__.py +4 -0
  23. vellum/workflows/triggers/base.py +125 -0
  24. vellum/workflows/triggers/manual.py +37 -0
  25. vellum/workflows/workflows/base.py +9 -9
  26. {vellum_ai-1.7.4.dist-info → vellum_ai-1.7.5.dist-info}/METADATA +1 -1
  27. {vellum_ai-1.7.4.dist-info → vellum_ai-1.7.5.dist-info}/RECORD +36 -29
  28. vellum_ee/assets/node-definitions.json +1 -1
  29. vellum_ee/workflows/display/base.py +26 -1
  30. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_inline_workflow_serialization.py +1 -1
  31. vellum_ee/workflows/display/tests/workflow_serialization/test_basic_tool_calling_node_serialization.py +1 -1
  32. vellum_ee/workflows/display/tests/workflow_serialization/test_manual_trigger_serialization.py +113 -0
  33. vellum_ee/workflows/display/workflows/base_workflow_display.py +63 -10
  34. {vellum_ai-1.7.4.dist-info → vellum_ai-1.7.5.dist-info}/LICENSE +0 -0
  35. {vellum_ai-1.7.4.dist-info → vellum_ai-1.7.5.dist-info}/WHEEL +0 -0
  36. {vellum_ai-1.7.4.dist-info → vellum_ai-1.7.5.dist-info}/entry_points.txt +0 -0
vellum/__init__.py CHANGED
@@ -353,6 +353,7 @@ from .client.types import (
353
353
  PaginatedSlimWorkflowDeploymentList,
354
354
  PaginatedTestSuiteRunExecutionList,
355
355
  PaginatedTestSuiteTestCaseList,
356
+ PaginatedWorkflowDeploymentReleaseList,
356
357
  PaginatedWorkflowReleaseTagReadList,
357
358
  PaginatedWorkflowSandboxExampleList,
358
359
  ParentContext,
@@ -1099,6 +1100,7 @@ __all__ = [
1099
1100
  "PaginatedSlimWorkflowDeploymentList",
1100
1101
  "PaginatedTestSuiteRunExecutionList",
1101
1102
  "PaginatedTestSuiteTestCaseList",
1103
+ "PaginatedWorkflowDeploymentReleaseList",
1102
1104
  "PaginatedWorkflowReleaseTagReadList",
1103
1105
  "PaginatedWorkflowSandboxExampleList",
1104
1106
  "ParentContext",
@@ -27,10 +27,10 @@ class BaseClientWrapper:
27
27
 
28
28
  def get_headers(self) -> typing.Dict[str, str]:
29
29
  headers: typing.Dict[str, str] = {
30
- "User-Agent": "vellum-ai/1.7.4",
30
+ "User-Agent": "vellum-ai/1.7.5",
31
31
  "X-Fern-Language": "Python",
32
32
  "X-Fern-SDK-Name": "vellum-ai",
33
- "X-Fern-SDK-Version": "1.7.4",
33
+ "X-Fern-SDK-Version": "1.7.5",
34
34
  **(self.get_custom_headers() or {}),
35
35
  }
36
36
  if self._api_version is not None:
@@ -6746,6 +6746,101 @@ client.workflow_deployments.update_workflow_release_tag(
6746
6746
  </dl>
6747
6747
 
6748
6748
 
6749
+ </dd>
6750
+ </dl>
6751
+ </details>
6752
+
6753
+ <details><summary><code>client.workflow_deployments.<a href="src/vellum/resources/workflow_deployments/client.py">list_workflow_deployment_releases</a>(...)</code></summary>
6754
+ <dl>
6755
+ <dd>
6756
+
6757
+ #### 📝 Description
6758
+
6759
+ <dl>
6760
+ <dd>
6761
+
6762
+ <dl>
6763
+ <dd>
6764
+
6765
+ List the Releases of the specified Workflow Deployment for the current Environment.
6766
+ </dd>
6767
+ </dl>
6768
+ </dd>
6769
+ </dl>
6770
+
6771
+ #### 🔌 Usage
6772
+
6773
+ <dl>
6774
+ <dd>
6775
+
6776
+ <dl>
6777
+ <dd>
6778
+
6779
+ ```python
6780
+ from vellum import Vellum
6781
+
6782
+ client = Vellum(
6783
+ api_version="YOUR_API_VERSION",
6784
+ api_key="YOUR_API_KEY",
6785
+ )
6786
+ client.workflow_deployments.list_workflow_deployment_releases(
6787
+ id="id",
6788
+ )
6789
+
6790
+ ```
6791
+ </dd>
6792
+ </dl>
6793
+ </dd>
6794
+ </dl>
6795
+
6796
+ #### ⚙️ Parameters
6797
+
6798
+ <dl>
6799
+ <dd>
6800
+
6801
+ <dl>
6802
+ <dd>
6803
+
6804
+ **id:** `str` — Either the Workflow Deployment's ID or its unique name
6805
+
6806
+ </dd>
6807
+ </dl>
6808
+
6809
+ <dl>
6810
+ <dd>
6811
+
6812
+ **limit:** `typing.Optional[int]` — Number of results to return per page.
6813
+
6814
+ </dd>
6815
+ </dl>
6816
+
6817
+ <dl>
6818
+ <dd>
6819
+
6820
+ **offset:** `typing.Optional[int]` — The initial index from which to return the results.
6821
+
6822
+ </dd>
6823
+ </dl>
6824
+
6825
+ <dl>
6826
+ <dd>
6827
+
6828
+ **ordering:** `typing.Optional[str]` — Which field to use when ordering the results.
6829
+
6830
+ </dd>
6831
+ </dl>
6832
+
6833
+ <dl>
6834
+ <dd>
6835
+
6836
+ **request_options:** `typing.Optional[RequestOptions]` — Request-specific configuration.
6837
+
6838
+ </dd>
6839
+ </dl>
6840
+ </dd>
6841
+ </dl>
6842
+
6843
+
6749
6844
  </dd>
6750
6845
  </dl>
6751
6846
  </details>
@@ -5,6 +5,7 @@ import typing
5
5
  from ...core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
6
6
  from ...core.request_options import RequestOptions
7
7
  from ...types.paginated_slim_workflow_deployment_list import PaginatedSlimWorkflowDeploymentList
8
+ from ...types.paginated_workflow_deployment_release_list import PaginatedWorkflowDeploymentReleaseList
8
9
  from ...types.paginated_workflow_release_tag_read_list import PaginatedWorkflowReleaseTagReadList
9
10
  from ...types.workflow_deployment_event_executions_response import WorkflowDeploymentEventExecutionsResponse
10
11
  from ...types.workflow_deployment_history_item import WorkflowDeploymentHistoryItem
@@ -387,6 +388,57 @@ class WorkflowDeploymentsClient:
387
388
  )
388
389
  return _response.data
389
390
 
391
+ def list_workflow_deployment_releases(
392
+ self,
393
+ id: str,
394
+ *,
395
+ limit: typing.Optional[int] = None,
396
+ offset: typing.Optional[int] = None,
397
+ ordering: typing.Optional[str] = None,
398
+ request_options: typing.Optional[RequestOptions] = None,
399
+ ) -> PaginatedWorkflowDeploymentReleaseList:
400
+ """
401
+ List the Releases of the specified Workflow Deployment for the current Environment.
402
+
403
+ Parameters
404
+ ----------
405
+ id : str
406
+ Either the Workflow Deployment's ID or its unique name
407
+
408
+ limit : typing.Optional[int]
409
+ Number of results to return per page.
410
+
411
+ offset : typing.Optional[int]
412
+ The initial index from which to return the results.
413
+
414
+ ordering : typing.Optional[str]
415
+ Which field to use when ordering the results.
416
+
417
+ request_options : typing.Optional[RequestOptions]
418
+ Request-specific configuration.
419
+
420
+ Returns
421
+ -------
422
+ PaginatedWorkflowDeploymentReleaseList
423
+
424
+
425
+ Examples
426
+ --------
427
+ from vellum import Vellum
428
+
429
+ client = Vellum(
430
+ api_version="YOUR_API_VERSION",
431
+ api_key="YOUR_API_KEY",
432
+ )
433
+ client.workflow_deployments.list_workflow_deployment_releases(
434
+ id="id",
435
+ )
436
+ """
437
+ _response = self._raw_client.list_workflow_deployment_releases(
438
+ id, limit=limit, offset=offset, ordering=ordering, request_options=request_options
439
+ )
440
+ return _response.data
441
+
390
442
  def retrieve_workflow_deployment_release(
391
443
  self, id: str, release_id_or_release_tag: str, *, request_options: typing.Optional[RequestOptions] = None
392
444
  ) -> WorkflowDeploymentRelease:
@@ -857,6 +909,65 @@ class AsyncWorkflowDeploymentsClient:
857
909
  )
858
910
  return _response.data
859
911
 
912
+ async def list_workflow_deployment_releases(
913
+ self,
914
+ id: str,
915
+ *,
916
+ limit: typing.Optional[int] = None,
917
+ offset: typing.Optional[int] = None,
918
+ ordering: typing.Optional[str] = None,
919
+ request_options: typing.Optional[RequestOptions] = None,
920
+ ) -> PaginatedWorkflowDeploymentReleaseList:
921
+ """
922
+ List the Releases of the specified Workflow Deployment for the current Environment.
923
+
924
+ Parameters
925
+ ----------
926
+ id : str
927
+ Either the Workflow Deployment's ID or its unique name
928
+
929
+ limit : typing.Optional[int]
930
+ Number of results to return per page.
931
+
932
+ offset : typing.Optional[int]
933
+ The initial index from which to return the results.
934
+
935
+ ordering : typing.Optional[str]
936
+ Which field to use when ordering the results.
937
+
938
+ request_options : typing.Optional[RequestOptions]
939
+ Request-specific configuration.
940
+
941
+ Returns
942
+ -------
943
+ PaginatedWorkflowDeploymentReleaseList
944
+
945
+
946
+ Examples
947
+ --------
948
+ import asyncio
949
+
950
+ from vellum import AsyncVellum
951
+
952
+ client = AsyncVellum(
953
+ api_version="YOUR_API_VERSION",
954
+ api_key="YOUR_API_KEY",
955
+ )
956
+
957
+
958
+ async def main() -> None:
959
+ await client.workflow_deployments.list_workflow_deployment_releases(
960
+ id="id",
961
+ )
962
+
963
+
964
+ asyncio.run(main())
965
+ """
966
+ _response = await self._raw_client.list_workflow_deployment_releases(
967
+ id, limit=limit, offset=offset, ordering=ordering, request_options=request_options
968
+ )
969
+ return _response.data
970
+
860
971
  async def retrieve_workflow_deployment_release(
861
972
  self, id: str, release_id_or_release_tag: str, *, request_options: typing.Optional[RequestOptions] = None
862
973
  ) -> WorkflowDeploymentRelease:
@@ -10,6 +10,7 @@ from ...core.jsonable_encoder import jsonable_encoder
10
10
  from ...core.pydantic_utilities import parse_obj_as
11
11
  from ...core.request_options import RequestOptions
12
12
  from ...types.paginated_slim_workflow_deployment_list import PaginatedSlimWorkflowDeploymentList
13
+ from ...types.paginated_workflow_deployment_release_list import PaginatedWorkflowDeploymentReleaseList
13
14
  from ...types.paginated_workflow_release_tag_read_list import PaginatedWorkflowReleaseTagReadList
14
15
  from ...types.workflow_deployment_event_executions_response import WorkflowDeploymentEventExecutionsResponse
15
16
  from ...types.workflow_deployment_history_item import WorkflowDeploymentHistoryItem
@@ -437,6 +438,66 @@ class RawWorkflowDeploymentsClient:
437
438
  raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
438
439
  raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
439
440
 
441
+ def list_workflow_deployment_releases(
442
+ self,
443
+ id: str,
444
+ *,
445
+ limit: typing.Optional[int] = None,
446
+ offset: typing.Optional[int] = None,
447
+ ordering: typing.Optional[str] = None,
448
+ request_options: typing.Optional[RequestOptions] = None,
449
+ ) -> HttpResponse[PaginatedWorkflowDeploymentReleaseList]:
450
+ """
451
+ List the Releases of the specified Workflow Deployment for the current Environment.
452
+
453
+ Parameters
454
+ ----------
455
+ id : str
456
+ Either the Workflow Deployment's ID or its unique name
457
+
458
+ limit : typing.Optional[int]
459
+ Number of results to return per page.
460
+
461
+ offset : typing.Optional[int]
462
+ The initial index from which to return the results.
463
+
464
+ ordering : typing.Optional[str]
465
+ Which field to use when ordering the results.
466
+
467
+ request_options : typing.Optional[RequestOptions]
468
+ Request-specific configuration.
469
+
470
+ Returns
471
+ -------
472
+ HttpResponse[PaginatedWorkflowDeploymentReleaseList]
473
+
474
+ """
475
+ _response = self._client_wrapper.httpx_client.request(
476
+ f"v1/workflow-deployments/{jsonable_encoder(id)}/releases",
477
+ base_url=self._client_wrapper.get_environment().default,
478
+ method="GET",
479
+ params={
480
+ "limit": limit,
481
+ "offset": offset,
482
+ "ordering": ordering,
483
+ },
484
+ request_options=request_options,
485
+ )
486
+ try:
487
+ if 200 <= _response.status_code < 300:
488
+ _data = typing.cast(
489
+ PaginatedWorkflowDeploymentReleaseList,
490
+ parse_obj_as(
491
+ type_=PaginatedWorkflowDeploymentReleaseList, # type: ignore
492
+ object_=_response.json(),
493
+ ),
494
+ )
495
+ return HttpResponse(response=_response, data=_data)
496
+ _response_json = _response.json()
497
+ except JSONDecodeError:
498
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
499
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
500
+
440
501
  def retrieve_workflow_deployment_release(
441
502
  self, id: str, release_id_or_release_tag: str, *, request_options: typing.Optional[RequestOptions] = None
442
503
  ) -> HttpResponse[WorkflowDeploymentRelease]:
@@ -894,6 +955,66 @@ class AsyncRawWorkflowDeploymentsClient:
894
955
  raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
895
956
  raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
896
957
 
958
+ async def list_workflow_deployment_releases(
959
+ self,
960
+ id: str,
961
+ *,
962
+ limit: typing.Optional[int] = None,
963
+ offset: typing.Optional[int] = None,
964
+ ordering: typing.Optional[str] = None,
965
+ request_options: typing.Optional[RequestOptions] = None,
966
+ ) -> AsyncHttpResponse[PaginatedWorkflowDeploymentReleaseList]:
967
+ """
968
+ List the Releases of the specified Workflow Deployment for the current Environment.
969
+
970
+ Parameters
971
+ ----------
972
+ id : str
973
+ Either the Workflow Deployment's ID or its unique name
974
+
975
+ limit : typing.Optional[int]
976
+ Number of results to return per page.
977
+
978
+ offset : typing.Optional[int]
979
+ The initial index from which to return the results.
980
+
981
+ ordering : typing.Optional[str]
982
+ Which field to use when ordering the results.
983
+
984
+ request_options : typing.Optional[RequestOptions]
985
+ Request-specific configuration.
986
+
987
+ Returns
988
+ -------
989
+ AsyncHttpResponse[PaginatedWorkflowDeploymentReleaseList]
990
+
991
+ """
992
+ _response = await self._client_wrapper.httpx_client.request(
993
+ f"v1/workflow-deployments/{jsonable_encoder(id)}/releases",
994
+ base_url=self._client_wrapper.get_environment().default,
995
+ method="GET",
996
+ params={
997
+ "limit": limit,
998
+ "offset": offset,
999
+ "ordering": ordering,
1000
+ },
1001
+ request_options=request_options,
1002
+ )
1003
+ try:
1004
+ if 200 <= _response.status_code < 300:
1005
+ _data = typing.cast(
1006
+ PaginatedWorkflowDeploymentReleaseList,
1007
+ parse_obj_as(
1008
+ type_=PaginatedWorkflowDeploymentReleaseList, # type: ignore
1009
+ object_=_response.json(),
1010
+ ),
1011
+ )
1012
+ return AsyncHttpResponse(response=_response, data=_data)
1013
+ _response_json = _response.json()
1014
+ except JSONDecodeError:
1015
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response.text)
1016
+ raise ApiError(status_code=_response.status_code, headers=dict(_response.headers), body=_response_json)
1017
+
897
1018
  async def retrieve_workflow_deployment_release(
898
1019
  self, id: str, release_id_or_release_tag: str, *, request_options: typing.Optional[RequestOptions] = None
899
1020
  ) -> AsyncHttpResponse[WorkflowDeploymentRelease]:
@@ -361,6 +361,7 @@ from .paginated_slim_tool_definition_list import PaginatedSlimToolDefinitionList
361
361
  from .paginated_slim_workflow_deployment_list import PaginatedSlimWorkflowDeploymentList
362
362
  from .paginated_test_suite_run_execution_list import PaginatedTestSuiteRunExecutionList
363
363
  from .paginated_test_suite_test_case_list import PaginatedTestSuiteTestCaseList
364
+ from .paginated_workflow_deployment_release_list import PaginatedWorkflowDeploymentReleaseList
364
365
  from .paginated_workflow_release_tag_read_list import PaginatedWorkflowReleaseTagReadList
365
366
  from .paginated_workflow_sandbox_example_list import PaginatedWorkflowSandboxExampleList
366
367
  from .parent_context import ParentContext
@@ -1068,6 +1069,7 @@ __all__ = [
1068
1069
  "PaginatedSlimWorkflowDeploymentList",
1069
1070
  "PaginatedTestSuiteRunExecutionList",
1070
1071
  "PaginatedTestSuiteTestCaseList",
1072
+ "PaginatedWorkflowDeploymentReleaseList",
1071
1073
  "PaginatedWorkflowReleaseTagReadList",
1072
1074
  "PaginatedWorkflowSandboxExampleList",
1073
1075
  "ParentContext",
@@ -0,0 +1,30 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from __future__ import annotations
4
+
5
+ import typing
6
+
7
+ import pydantic
8
+ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel, update_forward_refs
9
+ from .workflow_deployment_release import WorkflowDeploymentRelease
10
+
11
+
12
+ class PaginatedWorkflowDeploymentReleaseList(UniversalBaseModel):
13
+ count: typing.Optional[int] = None
14
+ next: typing.Optional[str] = None
15
+ previous: typing.Optional[str] = None
16
+ results: typing.Optional[typing.List[WorkflowDeploymentRelease]] = None
17
+
18
+ if IS_PYDANTIC_V2:
19
+ model_config: typing.ClassVar[pydantic.ConfigDict] = pydantic.ConfigDict(extra="allow", frozen=True) # type: ignore # Pydantic v2
20
+ else:
21
+
22
+ class Config:
23
+ frozen = True
24
+ smart_union = True
25
+ extra = pydantic.Extra.allow
26
+
27
+
28
+ from .array_vellum_value import ArrayVellumValue # noqa: E402, F401, I001
29
+
30
+ update_forward_refs(PaginatedWorkflowDeploymentReleaseList)
@@ -8,10 +8,12 @@ VellumErrorCodeEnum = typing.Union[
8
8
  "INVALID_INPUTS",
9
9
  "PROVIDER_ERROR",
10
10
  "PROVIDER_CREDENTIALS_UNAVAILABLE",
11
+ "INTEGRATION_CREDENTIALS_UNAVAILABLE",
11
12
  "REQUEST_TIMEOUT",
12
13
  "INTERNAL_SERVER_ERROR",
13
14
  "USER_DEFINED_ERROR",
14
15
  "WORKFLOW_CANCELLED",
16
+ "NODE_CANCELLED",
15
17
  ],
16
18
  typing.Any,
17
19
  ]
@@ -12,9 +12,11 @@ VellumSdkErrorCodeEnum = typing.Union[
12
12
  "INVALID_TEMPLATE",
13
13
  "INTERNAL_ERROR",
14
14
  "PROVIDER_CREDENTIALS_UNAVAILABLE",
15
+ "INTEGRATION_CREDENTIALS_UNAVAILABLE",
15
16
  "PROVIDER_ERROR",
16
17
  "USER_DEFINED_ERROR",
17
18
  "WORKFLOW_CANCELLED",
19
+ "NODE_CANCELLED",
18
20
  "NODE_EXECUTION",
19
21
  ],
20
22
  typing.Any,
@@ -7,9 +7,11 @@ WorkflowExecutionEventErrorCode = typing.Union[
7
7
  "WORKFLOW_INITIALIZATION",
8
8
  "WORKFLOW_CANCELLED",
9
9
  "PROVIDER_CREDENTIALS_UNAVAILABLE",
10
+ "INTEGRATION_CREDENTIALS_UNAVAILABLE",
10
11
  "NODE_EXECUTION_COUNT_LIMIT_REACHED",
11
12
  "INTERNAL_SERVER_ERROR",
12
13
  "NODE_EXECUTION",
14
+ "NODE_CANCELLED",
13
15
  "LLM_PROVIDER",
14
16
  "INVALID_TEMPLATE",
15
17
  "INVALID_INPUTS",
@@ -0,0 +1,3 @@
1
+ # WARNING: This file will be removed in a future release. Please import from "vellum.client" instead.
2
+
3
+ from vellum.client.types.paginated_workflow_deployment_release_list import *
@@ -1,5 +1,7 @@
1
1
  from .edge import Edge
2
+ from .trigger_edge import TriggerEdge
2
3
 
3
4
  __all__ = [
4
5
  "Edge",
6
+ "TriggerEdge",
5
7
  ]
@@ -0,0 +1,67 @@
1
+ from typing import TYPE_CHECKING, Any, Type
2
+
3
+ if TYPE_CHECKING:
4
+ from vellum.workflows.nodes.bases import BaseNode
5
+ from vellum.workflows.triggers.base import BaseTrigger
6
+
7
+
8
+ class TriggerEdge:
9
+ """
10
+ Represents an edge from a Trigger to a Node in the workflow graph.
11
+
12
+ TriggerEdge is analogous to Edge, but connects triggers to nodes instead of
13
+ nodes to nodes. These edges define which nodes should be executed when a
14
+ particular trigger fires.
15
+
16
+ Examples:
17
+ ManualTrigger >> MyNode # Creates TriggerEdge(ManualTrigger, MyNode)
18
+ SlackTrigger >> ProcessNode # Creates TriggerEdge(SlackTrigger, ProcessNode)
19
+
20
+ Attributes:
21
+ trigger_class: The trigger class that initiates execution
22
+ to_node: The node that should execute when the trigger fires
23
+ """
24
+
25
+ def __init__(self, trigger_class: Type["BaseTrigger"], to_node: Type["BaseNode"]):
26
+ """
27
+ Initialize a TriggerEdge.
28
+
29
+ Args:
30
+ trigger_class: The trigger class that initiates execution
31
+ to_node: The node class that should execute when triggered
32
+ """
33
+ self.trigger_class = trigger_class
34
+ self.to_node = to_node
35
+
36
+ def __eq__(self, other: Any) -> bool:
37
+ """
38
+ Two TriggerEdges are equal if they have the same trigger and target node.
39
+
40
+ Args:
41
+ other: Another object to compare with
42
+
43
+ Returns:
44
+ True if both edges connect the same trigger to the same node
45
+ """
46
+ if not isinstance(other, TriggerEdge):
47
+ return False
48
+
49
+ return self.trigger_class == other.trigger_class and self.to_node == other.to_node
50
+
51
+ def __hash__(self) -> int:
52
+ """
53
+ Hash based on trigger and target node for set/dict operations.
54
+
55
+ Returns:
56
+ Hash value for this edge
57
+ """
58
+ return hash((self.trigger_class, self.to_node))
59
+
60
+ def __repr__(self) -> str:
61
+ """
62
+ String representation showing the trigger-to-node connection.
63
+
64
+ Returns:
65
+ String in format "TriggerName >> NodeName"
66
+ """
67
+ return f"{self.trigger_class.__name__} >> {self.to_node.__name__}"
@@ -227,6 +227,45 @@ mock_node_uuid = str(uuid4_from_hash(MockNode.__qualname__))
227
227
  "outputs": {
228
228
  "example": "foo",
229
229
  },
230
+ "final_state": None,
231
+ },
232
+ "parent": None,
233
+ "links": None,
234
+ },
235
+ ),
236
+ (
237
+ WorkflowExecutionFulfilledEvent(
238
+ id=UUID("123e4567-e89b-12d3-a456-426614174000"),
239
+ timestamp=datetime(2024, 1, 1, 12, 0, 0, tzinfo=timezone.utc),
240
+ trace_id=UUID("123e4567-e89b-12d3-a456-426614174000"),
241
+ span_id=UUID("123e4567-e89b-12d3-a456-426614174000"),
242
+ body=WorkflowExecutionFulfilledBody(
243
+ workflow_definition=MockWorkflow,
244
+ outputs=MockNode.Outputs(
245
+ example="foo",
246
+ ),
247
+ final_state=BaseState(writable_value=42),
248
+ ),
249
+ ),
250
+ {
251
+ "id": "123e4567-e89b-12d3-a456-426614174000",
252
+ "api_version": "2024-10-25",
253
+ "timestamp": "2024-01-01T12:00:00Z",
254
+ "trace_id": "123e4567-e89b-12d3-a456-426614174000",
255
+ "span_id": "123e4567-e89b-12d3-a456-426614174000",
256
+ "name": "workflow.execution.fulfilled",
257
+ "body": {
258
+ "workflow_definition": {
259
+ "id": mock_workflow_uuid,
260
+ "name": "MockWorkflow",
261
+ "module": module_root + ["events", "tests", "test_event"],
262
+ },
263
+ "outputs": {
264
+ "example": "foo",
265
+ },
266
+ "final_state": {
267
+ "writable_value": 42,
268
+ },
230
269
  },
231
270
  "parent": None,
232
271
  "links": None,
@@ -427,6 +466,7 @@ mock_node_uuid = str(uuid4_from_hash(MockNode.__qualname__))
427
466
  "node.execution.initiated",
428
467
  "workflow.execution.streaming",
429
468
  "workflow.execution.fulfilled",
469
+ "workflow.execution.fulfilled_with_state",
430
470
  "workflow.execution.rejected",
431
471
  "node.execution.streaming",
432
472
  "node.execution.fulfilled",
@@ -137,22 +137,34 @@ class WorkflowExecutionStreamingEvent(_BaseWorkflowEvent):
137
137
  return self.body.output
138
138
 
139
139
 
140
- class WorkflowExecutionFulfilledBody(_BaseWorkflowExecutionBody, Generic[OutputsType]):
140
+ class WorkflowExecutionFulfilledBody(_BaseWorkflowExecutionBody, Generic[OutputsType, StateType]):
141
141
  outputs: OutputsType
142
+ final_state: Optional[StateType] = None
142
143
 
143
144
  @field_serializer("outputs")
144
145
  def serialize_outputs(self, outputs: OutputsType, _info: Any) -> Dict[str, Any]:
145
146
  return default_serializer(outputs)
146
147
 
148
+ @field_serializer("final_state")
149
+ def serialize_final_state(self, final_state: Optional[StateType], _info: Any) -> Optional[Dict[str, Any]]:
150
+ if final_state is None:
151
+ return None
152
+ state_dict = {k: v for k, v in final_state if k != "meta"}
153
+ return default_serializer(state_dict)
147
154
 
148
- class WorkflowExecutionFulfilledEvent(_BaseWorkflowEvent, Generic[OutputsType]):
155
+
156
+ class WorkflowExecutionFulfilledEvent(_BaseWorkflowEvent, Generic[OutputsType, StateType]):
149
157
  name: Literal["workflow.execution.fulfilled"] = "workflow.execution.fulfilled"
150
- body: WorkflowExecutionFulfilledBody[OutputsType]
158
+ body: WorkflowExecutionFulfilledBody[OutputsType, StateType]
151
159
 
152
160
  @property
153
161
  def outputs(self) -> OutputsType:
154
162
  return self.body.outputs
155
163
 
164
+ @property
165
+ def final_state(self) -> Optional[StateType]:
166
+ return self.body.final_state
167
+
156
168
 
157
169
  class WorkflowExecutionRejectedBody(_BaseWorkflowExecutionBody):
158
170
  error: WorkflowError