Skip to content
Merged
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.14.1"
version = "2.14.2"
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
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from pydantic import TypeAdapter

from uipath.platform.chat._llm_gateway_service import _cleanup_schema
from uipath.platform.common import UiPathConfig

from .._execution_context import execution_id_context, span_collector_context
from ._llm_mocker import LLMMocker
Expand Down Expand Up @@ -98,9 +99,17 @@ async def response(
"workloadInfo": workload_info,
"traceId": trace_id,
"parentSpanId": parent_span_id,
"folderKey": UiPathConfig.folder_key,
}

logger.info("simulate-component: calling API for '%s'", tool_name)
logger.info(
"simulate-component: calling API for '%s' "
"(traceId=%s, parentSpanId=%s, folderKey=%s)",
tool_name,
trace_id,
parent_span_id,
UiPathConfig.folder_key,
)
try:
service = _create_simulate_component_service()
result = await service.simulate(payload)
Expand Down
95 changes: 95 additions & 0 deletions packages/uipath/tests/cli/eval/mocks/test_simulate_component.py
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,54 @@ def sync_tool() -> int:
assert result == 42
clear_execution_context()

@pytest.mark.asyncio
async def test_payload_includes_folder_key_from_config(self, monkeypatch):
monkeypatch.setenv("UIPATH_FOLDER_KEY", "folder-abc")
ctx = _make_context("my_tool", workload_id="wl-fk")
captured: list[dict[str, Any]] = []

async def _capture(payload, **kwargs):
captured.append(payload)
return {"status": 1, "simulatedOutput": "ok"}

svc_mock = MagicMock()
svc_mock.simulate = _capture

@mockable()
async def my_tool() -> str:
raise NotImplementedError()

set_execution_context(ctx, _mock_span_collector, "exec-fk")
with patch(_SIMULATE_PATH, return_value=svc_mock):
await my_tool()

assert captured[0]["folderKey"] == "folder-abc"
clear_execution_context()

@pytest.mark.asyncio
async def test_payload_folder_key_is_none_when_not_set(self, monkeypatch):
monkeypatch.delenv("UIPATH_FOLDER_KEY", raising=False)
ctx = _make_context("my_tool", workload_id="wl-fk2")
captured: list[dict[str, Any]] = []
Comment thread
AAgnihotry marked this conversation as resolved.

async def _capture(payload, **kwargs):
captured.append(payload)
return {"status": 1, "simulatedOutput": "ok"}

svc_mock = MagicMock()
svc_mock.simulate = _capture

@mockable()
async def my_tool() -> str:
raise NotImplementedError()

set_execution_context(ctx, _mock_span_collector, "exec-fk2")
with patch(_SIMULATE_PATH, return_value=svc_mock):
await my_tool()

assert captured[0]["folderKey"] is None
clear_execution_context()

@pytest.mark.asyncio
async def test_payload_uses_configured_component_id_not_invoked_name(self):
"""componentId in payload must be the configured ID, not the normalised call name."""
Expand Down Expand Up @@ -346,6 +394,53 @@ def test_returns_none_when_spans_empty(self):

clear_execution_context()

def test_returns_valid_trace_and_span_ids(self):
from opentelemetry import context as context_api
from opentelemetry import trace
from opentelemetry.trace import NonRecordingSpan, SpanContext, TraceFlags

span_ctx = SpanContext(
trace_id=0x1234567890ABCDEF1234567890ABCDEF,
span_id=0xFEDCBA0987654321,
is_remote=False,
trace_flags=TraceFlags(TraceFlags.SAMPLED),
)
span = NonRecordingSpan(context=span_ctx)
token = context_api.attach(trace.set_span_in_context(span))
try:
trace_id, span_id = SimulateComponentMocker._get_span_context()
assert trace_id == "1234567890abcdef1234567890abcdef"
assert span_id == "fedcba0987654321"
finally:
context_api.detach(token)


class TestPayloadLogging:
@pytest.mark.asyncio
async def test_log_includes_trace_and_folder_key(self, monkeypatch, caplog):
monkeypatch.setenv("UIPATH_FOLDER_KEY", "folder-log")
ctx = _make_context("my_tool", workload_id="wl-log")
svc_mock = _make_service_mock({"status": 1, "simulatedOutput": "ok"})

@mockable()
async def my_tool() -> str:
raise NotImplementedError()

set_execution_context(ctx, _mock_span_collector, "exec-log")
import logging

with caplog.at_level(
logging.INFO, logger="uipath.eval.mocks._simulate_component_mocker"
):
with patch(_SIMULATE_PATH, return_value=svc_mock):
await my_tool()

log_line = next(r.message for r in caplog.records if "calling API" in r.message)
assert "folderKey=folder-log" in log_line
assert "traceId=" in log_line
assert "parentSpanId=" in log_line
clear_execution_context()


# ---------------------------------------------------------------------------
# MockerFactory — unknown strategy raises ValueError
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