From 2f6f5f4a2599b1c480128fec008ad1ccc61677d3 Mon Sep 17 00:00:00 2001 From: Cristian Pufu Date: Sat, 29 Nov 2025 16:03:22 +0200 Subject: [PATCH] fix: debug wait for terminate --- pyproject.toml | 4 ++-- src/uipath/dev/models/execution.py | 2 +- src/uipath/dev/services/debug_bridge.py | 12 ++++++++---- src/uipath/dev/services/run_service.py | 13 ++++++++----- uv.lock | 10 +++++----- 5 files changed, 24 insertions(+), 17 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 127548c..2f617f7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,11 +1,11 @@ [project] name = "uipath-dev" -version = "0.0.7" +version = "0.0.8" description = "UiPath Developer Console" readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.11" dependencies = [ - "uipath-runtime>=0.0.21, <0.1.0", + "uipath-runtime>=0.1.0, <0.2.0", "textual>=6.6.0, <7.0.0", "pyperclip>=1.11.0, <2.0.0", ] diff --git a/src/uipath/dev/models/execution.py b/src/uipath/dev/models/execution.py index d4a7d1f..91f3524 100644 --- a/src/uipath/dev/models/execution.py +++ b/src/uipath/dev/models/execution.py @@ -28,7 +28,7 @@ def __init__( self.conversational = conversational self.debug = debug self.resume_data: dict[str, Any] | None = None - self.output_data: dict[str, Any] | None = None + self.output_data: dict[str, Any] | str | None = None self.start_time = datetime.now() self.end_time: datetime | None = None self.status = "pending" # pending, running, completed, failed, suspended diff --git a/src/uipath/dev/services/debug_bridge.py b/src/uipath/dev/services/debug_bridge.py index 8c9bfd7..f43b9c8 100644 --- a/src/uipath/dev/services/debug_bridge.py +++ b/src/uipath/dev/services/debug_bridge.py @@ -18,7 +18,7 @@ def __init__(self): """Initialize the debug bridge.""" self._connected = False self._resume_event = asyncio.Event() - self._quit_requested = False + self._terminate_event = asyncio.Event() self._breakpoints: list[str] | Literal["*"] = "*" # Default: step mode # Callbacks to UI @@ -31,13 +31,13 @@ def __init__(self): async def connect(self) -> None: """Establish connection to debugger.""" self._connected = True - self._quit_requested = False logger.debug("Debug bridge connected") async def disconnect(self) -> None: """Close connection to debugger.""" self._connected = False self._resume_event.set() # Unblock any waiting tasks + self._terminate_event.set() logger.debug("Debug bridge disconnected") async def emit_execution_started(self, **kwargs: Any) -> None: @@ -83,16 +83,20 @@ async def wait_for_resume(self) -> Any: self._resume_event.clear() await self._resume_event.wait() - if self._quit_requested: + if self._terminate_event.is_set(): raise UiPathDebugQuitError("Debug session quit requested") + async def wait_for_terminate(self) -> None: + """Wait for terminate command from debugger.""" + await self._terminate_event.wait() + def resume(self) -> None: """Signal that execution should resume (called from UI buttons).""" self._resume_event.set() def quit(self) -> None: """Signal that execution should quit (called from UI stop button).""" - self._quit_requested = True + self._terminate_event.set() self._resume_event.set() def get_breakpoints(self) -> list[str] | Literal["*"]: diff --git a/src/uipath/dev/services/run_service.py b/src/uipath/dev/services/run_service.py index 3f7887d..b72ea53 100644 --- a/src/uipath/dev/services/run_service.py +++ b/src/uipath/dev/services/run_service.py @@ -2,6 +2,7 @@ from __future__ import annotations +import json import traceback from datetime import datetime from typing import Any, Callable @@ -17,6 +18,7 @@ ) from uipath.runtime.debug import UiPathDebugRuntime from uipath.runtime.errors import UiPathErrorContract, UiPathRuntimeError +from uipath.runtime.events import UiPathRuntimeStateEvent from uipath.dev.infrastructure import RunContextExporter, RunContextLogHandler from uipath.dev.models import ExecutionRun, LogMessage, TraceMessage @@ -111,8 +113,8 @@ async def execute(self, run: ExecutionRun) -> None: debug_bridge = TextualDebugBridge() # Connect callbacks - debug_bridge.on_state_update = lambda event: self._handle_state_update( - run.id, event + debug_bridge.on_state_update = lambda state: self._handle_state_update( + run.id, state ) debug_bridge.on_breakpoint_hit = lambda bp: self._handle_breakpoint_hit( run.id, bp @@ -248,10 +250,11 @@ def get_debug_bridge(self, run_id: str) -> TextualDebugBridge | None: """Get the debug bridge for a run.""" return self.debug_bridges.get(run_id) - def _handle_state_update(self, run_id: str, event) -> None: + def _handle_state_update(self, run_id: str, state: UiPathRuntimeStateEvent) -> None: """Handle state update from debug runtime.""" - # You can add more logic here later if needed - pass + run = self.runs.get(run_id) + if run: + self._add_info_log(run, json.dumps(state.payload)) def _handle_debug_started(self, run_id: str) -> None: """Handle debug started event.""" diff --git a/uv.lock b/uv.lock index 5287c21..1ea704c 100644 --- a/uv.lock +++ b/uv.lock @@ -1002,7 +1002,7 @@ wheels = [ [[package]] name = "uipath-dev" -version = "0.0.7" +version = "0.0.8" source = { editable = "." } dependencies = [ { name = "pyperclip" }, @@ -1029,7 +1029,7 @@ dev = [ requires-dist = [ { name = "pyperclip", specifier = ">=1.11.0,<2.0.0" }, { name = "textual", specifier = ">=6.6.0,<7.0.0" }, - { name = "uipath-runtime", specifier = ">=0.0.21,<0.1.0" }, + { name = "uipath-runtime", specifier = ">=0.1.0,<0.2.0" }, ] [package.metadata.requires-dev] @@ -1049,14 +1049,14 @@ dev = [ [[package]] name = "uipath-runtime" -version = "0.0.21" +version = "0.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "uipath-core" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/8b/f8/2128bfd7add45e2f596955c03161ed69a365bab68a5d3c6238dcf5e2a548/uipath_runtime-0.0.21.tar.gz", hash = "sha256:9e25051f9168101cceb5e553149519f7d05764a847fea3fa0f4ec25d42e56fcb", size = 87722, upload-time = "2025-11-26T14:44:11.531Z" } +sdist = { url = "https://files.pythonhosted.org/packages/7b/5f/b48eaa87501ccffb067878ff99773fa89fbc1cafa8ab736d8fd5ae099b59/uipath_runtime-0.1.0.tar.gz", hash = "sha256:2a262eb29faeb1d62158ccaf1d1ec44752813625fdbcab5671a625c999c433ac", size = 87980, upload-time = "2025-11-29T13:10:32.269Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/de/fa/677a787cc6d02791d3c0a25ec0b83dd575e331dcd81bcae92fc668013aac/uipath_runtime-0.0.21-py3-none-any.whl", hash = "sha256:6459c451e707e9bf3308a9cd126a1dde11b9f752af7b2914f2df85561199ee7a", size = 33953, upload-time = "2025-11-26T14:44:09.988Z" }, + { url = "https://files.pythonhosted.org/packages/84/2a/39364e985269ac27b6b78d0323e6f516e25287bca87938a2088442b5cf06/uipath_runtime-0.1.0-py3-none-any.whl", hash = "sha256:997b53737fc6f22bb2e80700fd45c6b0a7912af6843fd4a103c58bdcf30f7fdd", size = 34207, upload-time = "2025-11-29T13:10:31.127Z" }, ] [[package]]