|
13 | 13 | from uipath.core.serialization import serialize_object |
14 | 14 | from uipath.core.triggers import ( |
15 | 15 | UiPathApiTrigger, |
| 16 | + UiPathIntegrationTrigger, |
16 | 17 | UiPathResumeTrigger, |
17 | 18 | UiPathResumeTriggerName, |
18 | 19 | UiPathResumeTriggerType, |
|
43 | 44 | WaitEphemeralIndex, |
44 | 45 | WaitEphemeralIndexRaw, |
45 | 46 | WaitEscalation, |
| 47 | + WaitIntegrationEvent, |
46 | 48 | WaitJob, |
47 | 49 | WaitJobRaw, |
48 | 50 | WaitSystemAgent, |
49 | 51 | WaitTask, |
50 | 52 | ) |
| 53 | +from uipath.platform.connections import EventArguments |
51 | 54 | from uipath.platform.context_grounding import DeepRagStatus, IndexStatus |
52 | 55 | from uipath.platform.context_grounding.context_grounding_index import ( |
53 | 56 | ContextGroundingIndex, |
@@ -401,6 +404,23 @@ async def read_trigger(self, trigger: UiPathResumeTrigger) -> Any | None: |
401 | 404 | f"Error fetching API trigger payload for inbox {trigger.api_resume.inbox_id}: {str(e)}", |
402 | 405 | ) from e |
403 | 406 |
|
| 407 | + case UiPathResumeTriggerType.INBOX: |
| 408 | + if trigger.integration_resume and trigger.integration_resume.inbox_id: |
| 409 | + try: |
| 410 | + inbox_payload = await uipath.jobs.retrieve_inbox_payload_async( |
| 411 | + trigger.integration_resume.inbox_id |
| 412 | + ) |
| 413 | + event_args = EventArguments.model_validate(inbox_payload) |
| 414 | + return await uipath.connections.retrieve_event_payload_async( |
| 415 | + event_args |
| 416 | + ) |
| 417 | + except Exception as e: |
| 418 | + raise UiPathFaultedTriggerError( |
| 419 | + ErrorCategory.SYSTEM, |
| 420 | + f"Failed to get trigger payload" |
| 421 | + f"Error fetching Inbox trigger payload for inbox {trigger.integration_resume.inbox_id}: {str(e)}", |
| 422 | + ) from e |
| 423 | + |
404 | 424 | case _: |
405 | 425 | raise UiPathFaultedTriggerError( |
406 | 426 | ErrorCategory.SYSTEM, |
@@ -461,6 +481,9 @@ async def create_trigger(self, suspend_value: Any) -> UiPathResumeTrigger: |
461 | 481 | case UiPathResumeTriggerType.API: |
462 | 482 | self._handle_api_trigger(suspend_value, resume_trigger) |
463 | 483 |
|
| 484 | + case UiPathResumeTriggerType.INBOX: |
| 485 | + await self._handle_inbox_trigger(suspend_value, resume_trigger) |
| 486 | + |
464 | 487 | case UiPathResumeTriggerType.DEEP_RAG: |
465 | 488 | await self._handle_deep_rag_job_trigger( |
466 | 489 | suspend_value, resume_trigger |
@@ -545,6 +568,8 @@ def _determine_trigger_type(self, value: Any) -> UiPathResumeTriggerType: |
545 | 568 | value, (DocumentExtractionValidation, WaitDocumentExtractionValidation) |
546 | 569 | ): |
547 | 570 | return UiPathResumeTriggerType.IXP_VS_ESCALATION |
| 571 | + if isinstance(value, WaitIntegrationEvent): |
| 572 | + return UiPathResumeTriggerType.INBOX |
548 | 573 | # default to API trigger |
549 | 574 | return UiPathResumeTriggerType.API |
550 | 575 |
|
@@ -579,6 +604,8 @@ def _determine_trigger_name(self, value: Any) -> UiPathResumeTriggerName: |
579 | 604 | return UiPathResumeTriggerName.BATCH_RAG |
580 | 605 | if isinstance(value, (DocumentExtraction, WaitDocumentExtraction)): |
581 | 606 | return UiPathResumeTriggerName.EXTRACTION |
| 607 | + if isinstance(value, WaitIntegrationEvent): |
| 608 | + return UiPathResumeTriggerName.INBOX |
582 | 609 | # default to API trigger |
583 | 610 | return UiPathResumeTriggerName.API |
584 | 611 |
|
@@ -901,6 +928,57 @@ def _handle_api_trigger( |
901 | 928 | inbox_id=str(uuid.uuid4()), request=serialize_object(value) |
902 | 929 | ) |
903 | 930 |
|
| 931 | + async def _handle_inbox_trigger( |
| 932 | + self, value: WaitIntegrationEvent, resume_trigger: UiPathResumeTrigger |
| 933 | + ) -> None: |
| 934 | + """Handle Inbox-type resume triggers. |
| 935 | +
|
| 936 | + Resolves `connection_name` (scoped to `connection_folder_path` when |
| 937 | + provided) to a connection id via the Connections service, populates |
| 938 | + `integration_resume` with the Integration Services configuration plus a |
| 939 | + freshly generated `inbox_id`. The Connections-service registration is |
| 940 | + performed server-side by Orchestrator's `CreateResumeTriggerTaskHandler` |
| 941 | + once the job suspends. |
| 942 | +
|
| 943 | + Args: |
| 944 | + value: The suspend value (WaitIntegrationEvent) |
| 945 | + resume_trigger: The resume trigger to populate |
| 946 | +
|
| 947 | + Raises: |
| 948 | + Exception: If no connection matches `connection_name`, or if more |
| 949 | + than one exact match is found. |
| 950 | + """ |
| 951 | + uipath = UiPath() |
| 952 | + connections = await uipath.connections.list_async( |
| 953 | + name=value.connection_name, |
| 954 | + folder_path=value.connection_folder_path, |
| 955 | + connector_key=value.connector, |
| 956 | + ) |
| 957 | + connection = next( |
| 958 | + (c for c in connections if c.name == value.connection_name), None |
| 959 | + ) |
| 960 | + if connection is None: |
| 961 | + raise Exception( |
| 962 | + f"No connection named '{value.connection_name}' " |
| 963 | + f"for connector '{value.connector}' found" |
| 964 | + + ( |
| 965 | + f" in folder '{value.connection_folder_path}'" |
| 966 | + if value.connection_folder_path |
| 967 | + else "" |
| 968 | + ) |
| 969 | + ) |
| 970 | + assert connection.id is not None |
| 971 | + |
| 972 | + resume_trigger.integration_resume = UiPathIntegrationTrigger( |
| 973 | + connector=value.connector, |
| 974 | + connection_id=connection.id, |
| 975 | + operation=value.operation, |
| 976 | + object_name=value.object_name, |
| 977 | + filter_expression=value.filter_expression, |
| 978 | + parameters=value.parameters, |
| 979 | + inbox_id=str(uuid.uuid4()), |
| 980 | + ) |
| 981 | + |
904 | 982 |
|
905 | 983 | class UiPathResumeTriggerHandler: |
906 | 984 | """Combined handler for creating and reading resume triggers. |
|
0 commit comments