diff --git a/packages/uipath-platform/pyproject.toml b/packages/uipath-platform/pyproject.toml index 80546ec3a..ac114087b 100644 --- a/packages/uipath-platform/pyproject.toml +++ b/packages/uipath-platform/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "uipath-platform" -version = "0.1.48" +version = "0.1.51" description = "HTTP client library for programmatic access to UiPath Platform" readme = { file = "README.md", content-type = "text/markdown" } requires-python = ">=3.11" diff --git a/packages/uipath-platform/src/uipath/platform/common/_span_utils.py b/packages/uipath-platform/src/uipath/platform/common/_span_utils.py index cd7e15e23..054bb3c9c 100644 --- a/packages/uipath-platform/src/uipath/platform/common/_span_utils.py +++ b/packages/uipath-platform/src/uipath/platform/common/_span_utils.py @@ -15,8 +15,8 @@ logger = logging.getLogger(__name__) -# SourceEnum.Robots = 4 (default for Python SDK / coded agents) -DEFAULT_SOURCE = 4 +# SourceEnum.CodedAgents = 10 (default for Python SDK / coded agents) +DEFAULT_SOURCE = 10 class AttachmentProvider(IntEnum): @@ -283,7 +283,7 @@ def otel_span_to_uipath_span( # Top-level fields for internal tracing schema execution_type = attributes_dict.get("executionType") agent_version = attributes_dict.get("agentVersion") - reference_id = attributes_dict.get("referenceId") + reference_id = attributes_dict.get("agentId") # Source: override via uipath.source attribute, else DEFAULT_SOURCE uipath_source = attributes_dict.get("uipath.source") diff --git a/packages/uipath-platform/src/uipath/platform/orchestrator/job.py b/packages/uipath-platform/src/uipath/platform/orchestrator/job.py index 7ade631e5..6464405b4 100644 --- a/packages/uipath-platform/src/uipath/platform/orchestrator/job.py +++ b/packages/uipath-platform/src/uipath/platform/orchestrator/job.py @@ -79,5 +79,5 @@ class Job(BaseModel): has_errors: Optional[bool] = Field(default=None, alias="HasErrors") has_warnings: Optional[bool] = Field(default=None, alias="HasWarnings") job_error: Optional[JobErrorInfo] = Field(default=None, alias="JobError") - folder_key: str = Field(alias="FolderKey") + folder_key: Optional[str] = Field(default=None, alias="FolderKey") id: int = Field(alias="Id") diff --git a/packages/uipath-platform/tests/services/test_span_utils.py b/packages/uipath-platform/tests/services/test_span_utils.py index 80cd0d2db..268ffc34c 100644 --- a/packages/uipath-platform/tests/services/test_span_utils.py +++ b/packages/uipath-platform/tests/services/test_span_utils.py @@ -363,8 +363,8 @@ def test_uipath_span_missing_execution_type_and_agent_version(self): assert span_dict["AgentVersion"] is None @patch.dict(os.environ, {"UIPATH_ORGANIZATION_ID": "test-org"}) - def test_uipath_span_source_defaults_to_robots(self): - """Test that Source defaults to 4 (Robots) and ignores attributes.source.""" + def test_uipath_span_source_defaults_to_coded_agents(self): + """Test that Source defaults to 10 (CodedAgents) and ignores attributes.source.""" mock_span = Mock(spec=OTelSpan) trace_id = 0x123456789ABCDEF0123456789ABCDEF0 @@ -387,9 +387,9 @@ def test_uipath_span_source_defaults_to_robots(self): uipath_span = _SpanUtils.otel_span_to_uipath_span(mock_span) span_dict = uipath_span.to_dict() - # Top-level Source should be 4 (Robots), string "runtime" is ignored - assert uipath_span.source == 4 - assert span_dict["Source"] == 4 + # Top-level Source should be 10 (CodedAgents), string "runtime" is ignored + assert uipath_span.source == 10 + assert span_dict["Source"] == 10 # attributes.source string should still be in Attributes JSON attrs = json.loads(span_dict["Attributes"]) @@ -408,7 +408,7 @@ def test_uipath_span_source_override_with_uipath_source(self): mock_span.name = "test-span" mock_span.parent = None mock_span.status.status_code = StatusCode.OK - # uipath.source=1 (Agents) overrides default of 4 (Robots) + # uipath.source=1 (Agents) overrides default of 10 (CodedAgents) mock_span.attributes = {"uipath.source": 1, "source": "runtime"} mock_span.events = [] mock_span.links = [] diff --git a/packages/uipath-platform/uv.lock b/packages/uipath-platform/uv.lock index 1e7878b10..3e7f668bf 100644 --- a/packages/uipath-platform/uv.lock +++ b/packages/uipath-platform/uv.lock @@ -1088,7 +1088,7 @@ dev = [ [[package]] name = "uipath-platform" -version = "0.1.48" +version = "0.1.51" source = { editable = "." } dependencies = [ { name = "httpx" }, diff --git a/packages/uipath/pyproject.toml b/packages/uipath/pyproject.toml index aba6ae877..6870318e3 100644 --- a/packages/uipath/pyproject.toml +++ b/packages/uipath/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "uipath" -version = "2.10.63" +version = "2.10.64" 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" diff --git a/packages/uipath/src/uipath/eval/evaluators/legacy_trajectory_evaluator.py b/packages/uipath/src/uipath/eval/evaluators/legacy_trajectory_evaluator.py index 17b69d0d0..cff0e8788 100644 --- a/packages/uipath/src/uipath/eval/evaluators/legacy_trajectory_evaluator.py +++ b/packages/uipath/src/uipath/eval/evaluators/legacy_trajectory_evaluator.py @@ -12,13 +12,13 @@ from ..._utils.constants import COMMUNITY_agents_SUFFIX from .._execution_context import eval_set_run_id_context +from .._helpers.evaluators_helpers import trace_to_str from .._helpers.helpers import is_empty_value from ..models import EvaluationResult from ..models.models import ( AgentExecution, LLMResponse, NumericEvaluationResult, - TrajectoryEvaluationTrace, UiPathEvaluationError, UiPathEvaluationErrorCategory, ) @@ -140,10 +140,7 @@ def _create_evaluation_prompt( and agent_run_history and isinstance(agent_run_history[0], ReadableSpan) ): - trajectory_trace = TrajectoryEvaluationTrace.from_readable_spans( - agent_run_history - ) - agent_run_history = str(trajectory_trace.spans) + agent_run_history = trace_to_str(agent_run_history) else: agent_run_history = str(agent_run_history) diff --git a/packages/uipath/src/uipath/tracing/_otel_exporters.py b/packages/uipath/src/uipath/tracing/_otel_exporters.py index 423473065..d2bf3a7c1 100644 --- a/packages/uipath/src/uipath/tracing/_otel_exporters.py +++ b/packages/uipath/src/uipath/tracing/_otel_exporters.py @@ -389,7 +389,7 @@ def _process_span_attributes(self, span_data: Dict[str, Any]) -> None: def _build_url(self, span_list: list[Dict[str, Any]]) -> str: """Construct the URL for the API request.""" trace_id = str(span_list[0]["TraceId"]) - return f"{self.base_url}/api/Traces/spans?traceId={trace_id}&source=Robots" + return f"{self.base_url}/api/Traces/spans?traceId={trace_id}&source=CodedAgents" def _send_with_retries( self, url: str, payload: list[Dict[str, Any]], max_retries: int = 4 diff --git a/packages/uipath/tests/evaluators/test_legacy_trajectory_evaluator.py b/packages/uipath/tests/evaluators/test_legacy_trajectory_evaluator.py new file mode 100644 index 000000000..687fce08d --- /dev/null +++ b/packages/uipath/tests/evaluators/test_legacy_trajectory_evaluator.py @@ -0,0 +1,64 @@ +import uuid + +from opentelemetry.sdk.trace import ReadableSpan + +from uipath.eval.evaluators import LegacyTrajectoryEvaluator +from uipath.eval.evaluators.base_legacy_evaluator import LegacyEvaluationCriteria +from uipath.eval.evaluators.legacy_trajectory_evaluator import ( + LegacyTrajectoryEvaluatorConfig, +) +from uipath.eval.models.models import LegacyEvaluatorCategory, LegacyEvaluatorType + + +def _legacy_trajectory_evaluator() -> LegacyTrajectoryEvaluator: + return LegacyTrajectoryEvaluator( + id=str(uuid.uuid4()), + name="Legacy trajectory", + config_type=LegacyTrajectoryEvaluatorConfig, + evaluation_criteria_type=LegacyEvaluationCriteria, + justification_type=str, + category=LegacyEvaluatorCategory.Trajectory, + type=LegacyEvaluatorType.Trajectory, + prompt="History:\n{{AgentRunHistory}}\nExpected:\n{{ExpectedAgentBehavior}}", + createdAt="2026-05-14T00:00:00Z", + updatedAt="2026-05-14T00:00:00Z", + ) + + +def test_legacy_trajectory_prompt_uses_compact_tool_history() -> None: + long_prompt = "SYSTEM_PROMPT_" + ("x" * 10_000) + spans = [ + ReadableSpan( + name="agent_llm_call", + start_time=0, + end_time=1, + attributes={ + "openinference.span.kind": "LLM", + "input.value": f'{{"messages": [{{"role": "system", "content": "{long_prompt}"}}]}}', + "output.value": '{"generations": []}', + }, + ), + ReadableSpan( + name="search_profiles", + start_time=1, + end_time=2, + attributes={ + "openinference.span.kind": "TOOL", + "tool.name": "search_profiles", + "input.value": '{"query": "mentor"}', + "output.value": '{"content": "found mentor profile"}', + "metadata": f'{{"agent_prompt": "{long_prompt}"}}', + }, + ), + ] + + prompt = _legacy_trajectory_evaluator()._create_evaluation_prompt( + expected_agent_behavior="The agent should search matching profiles.", + agent_run_history=spans, + ) + + assert "SYSTEM_PROMPT_" not in prompt + assert "Tool: search_profiles" in prompt + assert '{"query": "mentor"}' in prompt + assert "found mentor profile" in prompt + assert "agent_llm_call" not in prompt diff --git a/packages/uipath/tests/tracing/test_otel_exporters.py b/packages/uipath/tests/tracing/test_otel_exporters.py index a55fa5d60..648dd9190 100644 --- a/packages/uipath/tests/tracing/test_otel_exporters.py +++ b/packages/uipath/tests/tracing/test_otel_exporters.py @@ -54,7 +54,7 @@ def exporter(mock_env_vars): exporter = LlmOpsHttpExporter() # Mock _build_url to include query parameters as in the actual implementation exporter._build_url = MagicMock( # type: ignore - return_value="https://test.uipath.com/org/tenant/llmopstenant_/api/Traces/spans?traceId=test-trace-id&source=Robots" + return_value="https://test.uipath.com/org/tenant/llmopstenant_/api/Traces/spans?traceId=test-trace-id&source=CodedAgents" ) yield exporter @@ -107,7 +107,7 @@ def test_export_success(exporter, mock_span): [{"span": "data", "TraceId": "test-trace-id"}] ) exporter.http_client.post.assert_called_once_with( - "https://test.uipath.com/org/tenant/llmopstenant_/api/Traces/spans?traceId=test-trace-id&source=Robots", + "https://test.uipath.com/org/tenant/llmopstenant_/api/Traces/spans?traceId=test-trace-id&source=CodedAgents", json=[{"span": "data", "TraceId": "test-trace-id"}], ) @@ -685,7 +685,7 @@ def exporter_with_mocks(self, mock_env_vars): with patch("uipath.tracing._otel_exporters.httpx.Client"): exporter = LlmOpsHttpExporter() exporter._build_url = MagicMock( # type: ignore - return_value="https://test.uipath.com/org/tenant/llmopstenant_/api/Traces/spans?traceId=test-trace-id&source=Robots" + return_value="https://test.uipath.com/org/tenant/llmopstenant_/api/Traces/spans?traceId=test-trace-id&source=CodedAgents" ) yield exporter diff --git a/packages/uipath/uv.lock b/packages/uipath/uv.lock index c51486b96..c89c40005 100644 --- a/packages/uipath/uv.lock +++ b/packages/uipath/uv.lock @@ -2543,7 +2543,7 @@ wheels = [ [[package]] name = "uipath" -version = "2.10.63" +version = "2.10.64" source = { editable = "." } dependencies = [ { name = "applicationinsights" }, @@ -2682,7 +2682,7 @@ dev = [ [[package]] name = "uipath-platform" -version = "0.1.48" +version = "0.1.51" source = { editable = "../uipath-platform" } dependencies = [ { name = "httpx" },