From f97a942d2fb7b2a2101223ae1d832d2fd4ede3e0 Mon Sep 17 00:00:00 2001 From: radu-mocanu Date: Tue, 2 Dec 2025 20:35:51 +0200 Subject: [PATCH] feat: convert faulted trigger errors to runtime errors --- pyproject.toml | 4 ++-- src/uipath/runtime/context.py | 26 +++++++++++++++---------- src/uipath/runtime/debug/runtime.py | 5 ++++- src/uipath/runtime/errors/codes.py | 1 + src/uipath/runtime/errors/exception.py | 14 +++++++++++++ src/uipath/runtime/resumable/runtime.py | 1 - uv.lock | 10 +++++----- 7 files changed, 42 insertions(+), 19 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 80376c8..1f03fd7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,11 +1,11 @@ [project] name = "uipath-runtime" -version = "0.1.2" +version = "0.1.3" description = "Runtime abstractions and interfaces for building agents and automation scripts in the UiPath ecosystem" readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.11" dependencies = [ - "uipath-core>=0.0.5, <0.1.0", + "uipath-core>=0.0.9, <0.1.0", ] classifiers = [ "Intended Audience :: Developers", diff --git a/src/uipath/runtime/context.py b/src/uipath/runtime/context.py index b773549..64accab 100644 --- a/src/uipath/runtime/context.py +++ b/src/uipath/runtime/context.py @@ -8,6 +8,7 @@ from typing import Any from pydantic import BaseModel, ConfigDict +from uipath.core.errors import UiPathFaultedTriggerError from uipath.core.tracing import UiPathTraceManager from uipath.runtime.errors import ( @@ -167,16 +168,21 @@ def __exit__(self, exc_type, exc_val, exc_tb): if exc_type: # Create error info from exception - if isinstance(exc_val, UiPathRuntimeError): - error_info = exc_val.error_info - else: - # Generic error - error_info = UiPathErrorContract( - code=f"ERROR_{exc_type.__name__}", - title=f"Runtime error: {exc_type.__name__}", - detail=str(exc_val), - category=UiPathErrorCategory.UNKNOWN, - ) + match exc_type: + case UiPathFaultedTriggerError(): + error_info = UiPathRuntimeError.from_resume_trigger_error( + exc_type + ).error_info + case UiPathRuntimeError(): + error_info = exc_val.error_info + case _: + # Generic error + error_info = UiPathErrorContract( + code=f"ERROR_{exc_type.__name__}", + title=f"Runtime error: {exc_type.__name__}", + detail=str(exc_val), + category=UiPathErrorCategory.UNKNOWN, + ) self.result.status = UiPathRuntimeStatus.FAULTED self.result.error = error_info diff --git a/src/uipath/runtime/debug/runtime.py b/src/uipath/runtime/debug/runtime.py index 922a673..f2861a7 100644 --- a/src/uipath/runtime/debug/runtime.py +++ b/src/uipath/runtime/debug/runtime.py @@ -4,6 +4,8 @@ import logging from typing import Any, AsyncGenerator, cast +from uipath.core.errors import UiPathPendingTriggerError + from uipath.runtime.base import ( UiPathExecuteOptions, UiPathRuntimeProtocol, @@ -273,7 +275,8 @@ async def _poll_trigger( except UiPathDebugQuitError: raise - except Exception as e: + + except UiPathPendingTriggerError as e: await self.debug_bridge.emit_state_update( UiPathRuntimeStateEvent( node_name="", diff --git a/src/uipath/runtime/errors/codes.py b/src/uipath/runtime/errors/codes.py index a0c102d..f198fdc 100644 --- a/src/uipath/runtime/errors/codes.py +++ b/src/uipath/runtime/errors/codes.py @@ -24,6 +24,7 @@ class UiPathErrorCode(str, Enum): INPUT_INVALID_JSON = "INPUT_INVALID_JSON" # HITL (Human-In-The-Loop) related errors + RESUME_TRIGGER_ERROR = "RESUME_TRIGGER_ERROR" INVOKED_PROCESS_FAILURE = "INVOKED_PROCESS_FAILURE" CREATE_RESUME_TRIGGER_ERROR = "CREATE_RESUME_TRIGGER_ERROR" RETRIEVE_RESUME_TRIGGER_ERROR = "RETRIEVE_PAYLOAD_ERROR" diff --git a/src/uipath/runtime/errors/exception.py b/src/uipath/runtime/errors/exception.py index 8ebcc10..1f6787d 100644 --- a/src/uipath/runtime/errors/exception.py +++ b/src/uipath/runtime/errors/exception.py @@ -4,6 +4,8 @@ import traceback from typing import Any +from uipath.core.errors import UiPathFaultedTriggerError + from uipath.runtime.errors.codes import UiPathErrorCode from uipath.runtime.errors.contract import UiPathErrorCategory, UiPathErrorContract @@ -99,3 +101,15 @@ def __init__( prefix=prefix, include_traceback=include_traceback, ) + + @classmethod + def from_resume_trigger_error( + cls, exc: UiPathFaultedTriggerError + ) -> "UiPathRuntimeError": + """Create UiPathRuntimeError from UiPathFaultedTriggerError.""" + return cls( + code=UiPathErrorCode.RESUME_TRIGGER_ERROR, + title="Resume trigger error", + detail=exc.message, + category=UiPathErrorCategory(exc.category), + ) diff --git a/src/uipath/runtime/resumable/runtime.py b/src/uipath/runtime/resumable/runtime.py index 75ca634..9ef64d4 100644 --- a/src/uipath/runtime/resumable/runtime.py +++ b/src/uipath/runtime/resumable/runtime.py @@ -67,7 +67,6 @@ async def execute( # Execute the delegate result = await self.delegate.execute(input, options=options) - # If suspended, create and persist trigger return await self._handle_suspension(result) diff --git a/uv.lock b/uv.lock index 9f1c8e8..b86d1d6 100644 --- a/uv.lock +++ b/uv.lock @@ -924,21 +924,21 @@ wheels = [ [[package]] name = "uipath-core" -version = "0.0.5" +version = "0.0.9" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "opentelemetry-instrumentation" }, { name = "opentelemetry-sdk" }, { name = "pydantic" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c6/be/575d6075bffb70de8f91feeef873d61d8e4051ac66edd97e14d639599ba4/uipath_core-0.0.5.tar.gz", hash = "sha256:b52e7455a45a1af504b6aa12844f14bd6d5bb69c98399b54c962723f5b0cacad", size = 77751, upload-time = "2025-11-24T06:48:40.943Z" } +sdist = { url = "https://files.pythonhosted.org/packages/4d/fa/d3b2f0ce3c81c051654431a9d05980b6308305bac23c6be2b59e395c1b16/uipath_core-0.0.9.tar.gz", hash = "sha256:362e3d649dc1f650d23d97da7f0afcd396a6a48f30abea9c956b6912198defef", size = 82156, upload-time = "2025-12-03T14:20:58.963Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/37/ae/9a2488196b98f0f9442573cdbfa146a2ae614aec22dabc28c9b34b4abf45/uipath_core-0.0.5-py3-none-any.whl", hash = "sha256:056b8f2fede1e23717ad0c356a300466ac8ca41dd03b9a5fecb6ab24dd5dc97e", size = 13183, upload-time = "2025-11-24T06:48:39.717Z" }, + { url = "https://files.pythonhosted.org/packages/c5/ea/0ba722d6c05d1821586e43126a2049184dcb6406d6bfdbcbd002447f2753/uipath_core-0.0.9-py3-none-any.whl", hash = "sha256:0f4770ea3b69025edc76e85697afb6ff0d9bf657b47d71d845ba6c38c12385ae", size = 22151, upload-time = "2025-12-03T14:20:57.473Z" }, ] [[package]] name = "uipath-runtime" -version = "0.1.2" +version = "0.1.3" source = { editable = "." } dependencies = [ { name = "uipath-core" }, @@ -960,7 +960,7 @@ dev = [ ] [package.metadata] -requires-dist = [{ name = "uipath-core", specifier = ">=0.0.5,<0.1.0" }] +requires-dist = [{ name = "uipath-core", specifier = ">=0.0.9,<0.1.0" }] [package.metadata.requires-dev] dev = [