From 8382add397f0bc95f87b4b3eb3509f01bbb1052d Mon Sep 17 00:00:00 2001 From: Andrei Tava Date: Wed, 19 Aug 2026 14:51:54 +0300 Subject: [PATCH 1/3] fix(debug): continue execution when initial resume wait times out --- src/uipath/runtime/debug/runtime.py | 7 ++++--- tests/test_debugger.py | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/uipath/runtime/debug/runtime.py b/src/uipath/runtime/debug/runtime.py index a64606a4..c300cb06 100644 --- a/src/uipath/runtime/debug/runtime.py +++ b/src/uipath/runtime/debug/runtime.py @@ -123,11 +123,12 @@ async def _stream_and_debug( try: await asyncio.wait_for(self.debug_bridge.wait_for_resume(), timeout=60.0) except asyncio.TimeoutError: + # Debug bridge likely disconnected: proceed unattended + # instead of failing the job. logger.warning( - "Initial resume wait timed out after 60s, assuming debug bridge disconnected" + "Initial resume wait timed out after 60s, assuming debug bridge " + "disconnected; continuing execution without debug commands" ) - yield UiPathRuntimeResult(status=UiPathRuntimeStatus.FAULTED) - return except UiPathDebugQuitError: logger.info("Debug session quit by user before execution started") yield UiPathRuntimeResult(status=UiPathRuntimeStatus.SUCCESSFUL) diff --git a/tests/test_debugger.py b/tests/test_debugger.py index cd82d2e7..7cd8ecbc 100644 --- a/tests/test_debugger.py +++ b/tests/test_debugger.py @@ -2,6 +2,7 @@ from __future__ import annotations +import asyncio from typing import Any, AsyncGenerator, Sequence, cast from unittest.mock import AsyncMock, Mock @@ -212,6 +213,30 @@ async def test_debug_runtime_streams_and_handles_breakpoints_and_state(): ) # initial + after breakpoint +@pytest.mark.asyncio +async def test_debug_runtime_continues_when_initial_resume_wait_times_out(): + """If no resume command arrives before the initial wait times out, + execution should continue unattended instead of faulting.""" + + runtime_impl = StreamingMockRuntime(node_sequence=["node-1", "node-2"]) + bridge = make_debug_bridge_mock() + + # Initial resume wait times out (debug bridge disconnected) + cast(AsyncMock, bridge.wait_for_resume).side_effect = asyncio.TimeoutError() + cast(Mock, bridge.get_breakpoints).return_value = [] + + debug_runtime = UiPathDebugRuntime( + delegate=runtime_impl, + debug_bridge=bridge, + ) + + result = await debug_runtime.execute({}) + + assert result.status == UiPathRuntimeStatus.SUCCESSFUL + assert result.output == {"visited_nodes": ["node-1", "node-2"]} + cast(AsyncMock, bridge.emit_execution_completed).assert_awaited_once_with(result) + + @pytest.mark.asyncio async def test_debug_runtime_waits_for_timer_resume_without_polling(): """Timer triggers should wait for external resume in debug mode.""" From 966f656a30e72a0b6d2f043bb54c81125e68637e Mon Sep 17 00:00:00 2001 From: Andrei Tava Date: Wed, 19 Aug 2026 14:58:34 +0300 Subject: [PATCH 2/3] refactor(debug): extract initial resume timeout constant --- src/uipath/runtime/debug/runtime.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/uipath/runtime/debug/runtime.py b/src/uipath/runtime/debug/runtime.py index c300cb06..8373ba92 100644 --- a/src/uipath/runtime/debug/runtime.py +++ b/src/uipath/runtime/debug/runtime.py @@ -35,6 +35,8 @@ logger = logging.getLogger(__name__) +INITIAL_RESUME_TIMEOUT_SECONDS = 60.0 + class UiPathDebugRuntime: """Specialized runtime for debug runs that streams events to a debug bridge.""" @@ -121,13 +123,16 @@ async def _stream_and_debug( # Starting in paused state - wait for breakpoints and resume try: - await asyncio.wait_for(self.debug_bridge.wait_for_resume(), timeout=60.0) + await asyncio.wait_for( + self.debug_bridge.wait_for_resume(), + timeout=INITIAL_RESUME_TIMEOUT_SECONDS, + ) except asyncio.TimeoutError: # Debug bridge likely disconnected: proceed unattended # instead of failing the job. logger.warning( - "Initial resume wait timed out after 60s, assuming debug bridge " - "disconnected; continuing execution without debug commands" + f"Initial resume wait timed out after {INITIAL_RESUME_TIMEOUT_SECONDS:g}s, " + "assuming debug bridge disconnected; continuing execution without debug commands" ) except UiPathDebugQuitError: logger.info("Debug session quit by user before execution started") From 5efc78578e4f98ffac8505f925b960664e56078f Mon Sep 17 00:00:00 2001 From: Andrei Tava Date: Wed, 19 Aug 2026 15:38:36 +0300 Subject: [PATCH 3/3] chore: bump version to 0.13.2 --- pyproject.toml | 2 +- uv.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 84af1782..8b5e5dc3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "uipath-runtime" -version = "0.13.1" +version = "0.13.2" 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" diff --git a/uv.lock b/uv.lock index 1350d745..97acb1ef 100644 --- a/uv.lock +++ b/uv.lock @@ -1153,7 +1153,7 @@ wheels = [ [[package]] name = "uipath-runtime" -version = "0.13.1" +version = "0.13.2" source = { editable = "." } dependencies = [ { name = "chardet" },