Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/uipath/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "uipath"
version = "2.13.13"
version = "2.13.14"
description = "Python SDK and CLI for UiPath Platform, enabling programmatic interaction with automation services, process management, and deployment tools."
readme = { file = "README.md", content-type = "text/markdown" }
requires-python = ">=3.11"
Expand Down
25 changes: 25 additions & 0 deletions packages/uipath/src/uipath/_cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import faulthandler
import importlib.metadata
import os
import sys
Expand All @@ -9,6 +10,30 @@
from uipath._utils._logs import setup_logging
from uipath.platform.constants import DOTENV_FILE


def _arm_startup_traceback_watchdog() -> None:
"""Dump all thread stacks to stderr if startup blocks past a threshold.

Armed at import time (before the lazy command modules load) so a hang
in module import or runtime construction is captured in the job logs,
where a stalled process is otherwise silent. Cancelled by the run
command once the runtime is ready, so a healthy run never dumps.
Opt-in via UIPATH_STARTUP_TRACEBACK_SECONDS; auto-enabled in the
serverless runtime with a conservative default.
"""
raw = os.environ.get("UIPATH_STARTUP_TRACEBACK_SECONDS")
if raw is None and os.environ.get("UIPATH_ENVIRONMENT_TAG") == "Serverless":
raw = "120"
try:
seconds = int(raw) if raw else 0
except ValueError:
seconds = 0
if seconds > 0:
faulthandler.dump_traceback_later(seconds, repeat=True, file=sys.stderr)


_arm_startup_traceback_watchdog()

# Windows console uses codepages (e.g. cp1252) that can't encode Unicode
# characters used by Rich spinners (Braille) and emoji output.
# When piped (not a TTY), keep the system encoding so the parent process
Expand Down
14 changes: 14 additions & 0 deletions packages/uipath/src/uipath/_cli/cli_run.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import asyncio
import faulthandler
import logging
from typing import Any

import click
Expand Down Expand Up @@ -41,6 +43,7 @@
from .middlewares import Middlewares

console = ConsoleLogger()
logger = logging.getLogger(__name__)


class _RunDiscoveryError(EntrypointDiscoveryException):
Expand Down Expand Up @@ -222,16 +225,19 @@ async def execute() -> None:
factory: UiPathRuntimeFactoryProtocol | None = None
governance_bootstrap: GovernanceBootstrap | None = None
try:
logger.info("[startup] resolving runtime factory")
factory = UiPathRuntimeFactoryRegistry.get(context=ctx)

resolved_entrypoint = entrypoint
if not resolved_entrypoint:
logger.info("[startup] discovering entrypoint")
available = factory.discover_entrypoints()
if len(available) == 1:
resolved_entrypoint = available[0]
else:
raise _RunDiscoveryError(available)

logger.info("[startup] loading factory settings")
factory_settings = await factory.get_settings()
trace_settings = (
factory_settings.trace_settings
Expand All @@ -248,6 +254,7 @@ async def execute() -> None:
if factory_settings
else None
)
logger.info("[startup] resolving governance")
governance_bootstrap = await resolve_governance(
agent_framework=agent_framework,
agent_type=agent_type,
Expand All @@ -262,11 +269,18 @@ async def execute() -> None:
governance_bootstrap.evaluator
)

logger.info(
"[startup] building runtime and compiling graph "
"(entrypoint=%s)",
resolved_entrypoint,
)
base_runtime = await factory.new_runtime(
resolved_entrypoint,
governance_runtime_id,
**new_runtime_kwargs,
)
logger.info("[startup] runtime ready, starting execution")
faulthandler.cancel_dump_traceback_later()

if governance_bootstrap is not None:
base_runtime = governance_bootstrap.wrap_runtime(
Expand Down
2 changes: 1 addition & 1 deletion packages/uipath/uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading